├── D3D12HelloNsightAftermath ├── D3D12HelloNsightAftermath.cpp ├── D3D12HelloNsightAftermath.h ├── D3D12HelloNsightAftermath.vcxproj ├── D3D12HelloNsightAftermath.vcxproj.filters ├── DXSample.cpp ├── DXSample.h ├── DXSampleHelper.h ├── LICENSE ├── Main.cpp ├── NsightAftermath.props ├── NsightAftermathGpuCrashTracker.cpp ├── NsightAftermathGpuCrashTracker.h ├── NsightAftermathHelpers.h ├── NsightAftermathShaderDatabase.cpp ├── NsightAftermathShaderDatabase.h ├── PixelShader.hlsl ├── README.md ├── Shader.hlsli ├── VertexShader.hlsl ├── Win32Application.cpp ├── Win32Application.h ├── d3dx12.h ├── stdafx.cpp └── stdafx.h ├── GpuCrashDump ├── D3D12HelloNsightAftermath-12252-1.nv-gpudmp ├── Extras │ ├── D3D12HelloNsightAftermath.pdb │ ├── LICENSE │ ├── Shaders │ │ ├── PixelShader.cso │ │ └── VertexShader.cso │ └── SourceShaders │ │ ├── PixelShader.hlsl │ │ ├── Shader.hlsli │ │ └── VertexShader.hlsl ├── README.md └── shader-59339c1ea8934740-00000210749de540.nvdbg ├── README.md └── VkHelloNsightAftermath ├── CMakeLists.txt ├── LICENSE.txt ├── NsightAftermathGpuCrashTracker.cpp ├── NsightAftermathGpuCrashTracker.h ├── NsightAftermathHelpers.h ├── NsightAftermathShaderDatabase.cpp ├── NsightAftermathShaderDatabase.h ├── README.md ├── VkHelloNsightAftermath.cpp ├── checkerboard.ppm.h ├── cmake ├── Copyright_cmake.txt ├── FindNsightAftermath.cmake ├── FindVulkan.cmake ├── FindVulkanHeaders.cmake ├── FindWayland.cmake ├── FindX11_XCB.cmake └── FindXCB.cmake ├── cube.frag ├── cube.vert ├── gettime.h ├── linmath.h └── object_type_string_helper.h /D3D12HelloNsightAftermath/D3D12HelloNsightAftermath.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #include "DXSample.h" 15 | #include 16 | 17 | // Enables the Nsight Aftermath code instrumentation for GPU crash dump creation. 18 | #define USE_NSIGHT_AFTERMATH 1 19 | 20 | #if USE_NSIGHT_AFTERMATH 21 | #include "NsightAftermathGpuCrashTracker.h" 22 | #endif 23 | 24 | using namespace DirectX; 25 | 26 | // Note that while ComPtr is used to manage the lifetime of resources on the CPU, 27 | // it has no understanding of the lifetime of resources on the GPU. Apps must account 28 | // for the GPU lifetime of resources to avoid destroying objects that may still be 29 | // referenced by the GPU. 30 | // An example of this can be found in the class method: OnDestroy(). 31 | using Microsoft::WRL::ComPtr; 32 | 33 | class D3D12HelloNsightAftermath : public DXSample 34 | { 35 | public: 36 | D3D12HelloNsightAftermath(UINT width, UINT height, std::wstring name); 37 | 38 | virtual void OnInit(); 39 | virtual void OnUpdate(); 40 | virtual void OnRender(); 41 | virtual void OnDestroy(); 42 | 43 | private: 44 | static const UINT FrameCount = 2; 45 | 46 | struct Vertex 47 | { 48 | XMFLOAT3 position; 49 | XMFLOAT4 color; 50 | }; 51 | 52 | struct SceneConstantBuffer 53 | { 54 | XMFLOAT4 offset; 55 | }; 56 | 57 | // Pipeline objects. 58 | CD3DX12_VIEWPORT m_viewport; 59 | CD3DX12_RECT m_scissorRect; 60 | ComPtr m_swapChain; 61 | ComPtr m_device; 62 | ComPtr m_renderTargets[FrameCount]; 63 | ComPtr m_commandAllocator; 64 | ComPtr m_commandQueue; 65 | ComPtr m_rootSignature; 66 | ComPtr m_rtvHeap; 67 | ComPtr m_cbvHeap; 68 | ComPtr m_pipelineState; 69 | ComPtr m_commandList; 70 | UINT m_rtvDescriptorSize; 71 | 72 | // App resources. 73 | ComPtr m_vertexBuffer; 74 | D3D12_VERTEX_BUFFER_VIEW m_vertexBufferView; 75 | ComPtr m_constantBuffer; 76 | SceneConstantBuffer m_constantBufferData; 77 | UINT8* m_pCbvDataBegin; 78 | 79 | // Synchronization objects. 80 | UINT m_frameIndex; 81 | HANDLE m_fenceEvent; 82 | ComPtr m_fence; 83 | UINT64 m_fenceValue; 84 | 85 | #if USE_NSIGHT_AFTERMATH 86 | // App-managed marker functionality 87 | UINT64 m_frameCounter; 88 | GpuCrashTracker::MarkerMap m_markerMap; 89 | 90 | // Nsight Aftermath instrumentation 91 | GFSDK_Aftermath_ContextHandle m_hAftermathCommandListContext; 92 | GpuCrashTracker m_gpuCrashTracker; 93 | #endif 94 | 95 | void LoadPipeline(); 96 | void LoadAssets(); 97 | void PopulateCommandList(); 98 | void WaitForPreviousFrame(); 99 | }; 100 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/D3D12HelloNsightAftermath.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {6F49D366-B5F1-432B-A3E8-5D1CA57865F9} 15 | Win32Proj 16 | D3D12HelloNsightAftermath 17 | D3D12HelloNsightAftermath 18 | 10.0 19 | 20 | 21 | 22 | Application 23 | true 24 | v143 25 | Unicode 26 | 27 | 28 | Application 29 | false 30 | v143 31 | true 32 | Unicode 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | true 47 | bin/$(Platform)/$(Configuration)/ 48 | obj/$(Platform)/$(Configuration)/ 49 | 50 | 51 | false 52 | bin/$(Platform)/$(Configuration)/ 53 | obj/$(Platform)/$(Configuration)/ 54 | 55 | 56 | 57 | Use 58 | Level3 59 | Disabled 60 | WIN32;_DEBUG;_WINDOWS;SHADERS_DIR="$(OutDir)Shaders";%(PreprocessorDefinitions) 61 | true 62 | $(OutDir)CompiledShaders;%(AdditionalIncludeDirectories) 63 | false 64 | 65 | 66 | Windows 67 | true 68 | d3d12.lib;dxgi.lib;d3dcompiler.lib;%(AdditionalDependencies) 69 | d3d12.dll 70 | 71 | 72 | true 73 | 74 | 75 | copy %(Identity) "$(OutDir)" > NUL 76 | $(OutDir)%(Identity) 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | Level3 86 | Use 87 | MaxSpeed 88 | true 89 | true 90 | WIN32;NDEBUG;_WINDOWS;SHADERS_DIR="$(OutDir)Shaders";%(PreprocessorDefinitions) 91 | true 92 | $(OutDir)CompiledShaders;%(AdditionalIncludeDirectories) 93 | false 94 | 95 | 96 | Windows 97 | true 98 | true 99 | true 100 | d3d12.lib;dxgi.lib;d3dcompiler.lib;%(AdditionalDependencies) 101 | d3d12.dll 102 | 103 | 104 | true 105 | 106 | 107 | copy %(Identity) "$(OutDir)" > NUL 108 | $(OutDir)%(Identity) 109 | true 110 | 111 | 112 | 113 | 114 | 6.0 115 | g_%(Filename) 116 | $(OutDir)CompiledShaders\%(Filename).h 117 | $(OutDir)Shaders\%(Filename).cso 118 | /Fd $(OutDir)Shaders\ 119 | true 120 | true 121 | false 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | Create 144 | Create 145 | 146 | 147 | 148 | 149 | Vertex 150 | VSMain 151 | 152 | 153 | Pixel 154 | PSMain 155 | 156 | 157 | 158 | 159 | true 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/D3D12HelloNsightAftermath.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {67bebf86-9539-4f7f-b9e9-a376519ec1f1} 6 | 7 | 8 | {954a8f61-1c3e-419b-baca-c5e2b83c689a} 9 | 10 | 11 | {09095d68-bcd7-45c4-b007-5c8ddb5d60a4} 12 | 13 | 14 | {8b0cb0c9-e0d8-4107-91c8-11654fac88e7} 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | 70 | 71 | Assets\Shaders 72 | 73 | 74 | Assets\Shaders 75 | 76 | 77 | 78 | 79 | Assets\Shaders 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/DXSample.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "stdafx.h" 13 | #include "DXSample.h" 14 | 15 | using namespace Microsoft::WRL; 16 | 17 | DXSample::DXSample(UINT width, UINT height, std::wstring name) : 18 | m_width(width), 19 | m_height(height), 20 | m_title(name), 21 | m_useWarpDevice(false) 22 | { 23 | WCHAR assetsPath[512]; 24 | GetAssetsPath(assetsPath, _countof(assetsPath)); 25 | m_assetsPath = assetsPath; 26 | 27 | m_aspectRatio = static_cast(width) / static_cast(height); 28 | } 29 | 30 | DXSample::~DXSample() 31 | { 32 | } 33 | 34 | // Helper function for resolving the full path of assets. 35 | std::wstring DXSample::GetAssetFullPath(LPCWSTR assetName) 36 | { 37 | return m_assetsPath + assetName; 38 | } 39 | 40 | // Helper function for acquiring the first available hardware adapter that supports Direct3D 12. 41 | // If no such adapter can be found, *ppAdapter will be set to nullptr. 42 | _Use_decl_annotations_ 43 | void DXSample::GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter) 44 | { 45 | ComPtr nvidia_adapter; 46 | ComPtr current_adapter; 47 | *ppAdapter = nullptr; 48 | 49 | for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, ¤t_adapter); ++adapterIndex) 50 | { 51 | DXGI_ADAPTER_DESC1 desc; 52 | current_adapter->GetDesc1(&desc); 53 | 54 | if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) 55 | { 56 | // Don't select the Basic Render Driver adapter. 57 | // If you want a software adapter, pass in "/warp" on the command line. 58 | continue; 59 | } 60 | 61 | // Check if it's an NVIDIA GPU (Vendor ID 0x10DE) 62 | if (desc.VendorId == 0x10DE) 63 | { 64 | // Check to see if this NVIDIA adapter supports Direct3D 12 65 | if (SUCCEEDED(D3D12CreateDevice(current_adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) 66 | { 67 | nvidia_adapter = current_adapter; // Found a suitable NVIDIA adapter 68 | break; // Prefer this NVIDIA adapter, so stop searching 69 | } 70 | } 71 | } 72 | 73 | if (nvidia_adapter) // If a suitable NVIDIA adapter was found 74 | { 75 | *ppAdapter = nvidia_adapter.Detach(); 76 | } 77 | else // No NVIDIA GPU supporting Direct3D 12 was found 78 | { 79 | MessageBox(nullptr, L"Could not find an NVIDIA GPU that supports Direct3D 12. Nsight Aftermath requires a compatible NVIDIA GPU.", L"NVIDIA GPU Required", MB_OK | MB_ICONERROR); 80 | exit(1); // Exit the application 81 | } 82 | } 83 | 84 | // Helper function for setting the window's title text. 85 | void DXSample::SetCustomWindowText(LPCWSTR text) 86 | { 87 | std::wstring windowText = m_title + L": " + text; 88 | SetWindowText(Win32Application::GetHwnd(), windowText.c_str()); 89 | } 90 | 91 | // Helper function for parsing any supplied command line args. 92 | _Use_decl_annotations_ 93 | void DXSample::ParseCommandLineArgs(WCHAR* argv[], int argc) 94 | { 95 | for (int i = 1; i < argc; ++i) 96 | { 97 | if (_wcsnicmp(argv[i], L"-warp", wcslen(argv[i])) == 0 || 98 | _wcsnicmp(argv[i], L"/warp", wcslen(argv[i])) == 0) 99 | { 100 | m_useWarpDevice = true; 101 | m_title = m_title + L" (WARP)"; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/DXSample.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #include "DXSampleHelper.h" 15 | #include "Win32Application.h" 16 | 17 | class DXSample 18 | { 19 | public: 20 | DXSample(UINT width, UINT height, std::wstring name); 21 | virtual ~DXSample(); 22 | 23 | virtual void OnInit() = 0; 24 | virtual void OnUpdate() = 0; 25 | virtual void OnRender() = 0; 26 | virtual void OnDestroy() = 0; 27 | 28 | // Samples override the event handlers to handle specific messages. 29 | virtual void OnKeyDown(UINT8 /*key*/) {} 30 | virtual void OnKeyUp(UINT8 /*key*/) {} 31 | 32 | // Accessors. 33 | UINT GetWidth() const { return m_width; } 34 | UINT GetHeight() const { return m_height; } 35 | const WCHAR* GetTitle() const { return m_title.c_str(); } 36 | 37 | void ParseCommandLineArgs(_In_reads_(argc) WCHAR* argv[], int argc); 38 | 39 | protected: 40 | std::wstring GetAssetFullPath(LPCWSTR assetName); 41 | void GetHardwareAdapter(_In_ IDXGIFactory2* pFactory, _Outptr_result_maybenull_ IDXGIAdapter1** ppAdapter); 42 | void SetCustomWindowText(LPCWSTR text); 43 | 44 | // Viewport dimensions. 45 | UINT m_width; 46 | UINT m_height; 47 | float m_aspectRatio; 48 | 49 | // Adapter info. 50 | bool m_useWarpDevice; 51 | 52 | private: 53 | // Root assets path. 54 | std::wstring m_assetsPath; 55 | 56 | // Window title. 57 | std::wstring m_title; 58 | }; 59 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/DXSampleHelper.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | #include 14 | 15 | // Note that while ComPtr is used to manage the lifetime of resources on the CPU, 16 | // it has no understanding of the lifetime of resources on the GPU. Apps must account 17 | // for the GPU lifetime of resources to avoid destroying objects that may still be 18 | // referenced by the GPU. 19 | using Microsoft::WRL::ComPtr; 20 | 21 | inline std::string HrToString(HRESULT hr) 22 | { 23 | char s_str[64] = {}; 24 | sprintf_s(s_str, "HRESULT of 0x%08X", static_cast(hr)); 25 | return std::string(s_str); 26 | } 27 | 28 | class HrException : public std::runtime_error 29 | { 30 | public: 31 | HrException(HRESULT hr) : std::runtime_error(HrToString(hr)), m_hr(hr) {} 32 | HRESULT Error() const { return m_hr; } 33 | private: 34 | const HRESULT m_hr; 35 | }; 36 | 37 | #define SAFE_RELEASE(p) if (p) (p)->Release() 38 | 39 | inline void ThrowIfFailed(HRESULT hr) 40 | { 41 | if (FAILED(hr)) 42 | { 43 | throw HrException(hr); 44 | } 45 | } 46 | 47 | inline void GetAssetsPath(_Out_writes_(pathSize) WCHAR* path, UINT pathSize) 48 | { 49 | if (path == nullptr) 50 | { 51 | throw std::exception(); 52 | } 53 | 54 | DWORD size = GetModuleFileName(nullptr, path, pathSize); 55 | if (size == 0 || size == pathSize) 56 | { 57 | // Method failed or path was truncated. 58 | throw std::exception(); 59 | } 60 | 61 | WCHAR* lastSlash = wcsrchr(path, L'\\'); 62 | if (lastSlash) 63 | { 64 | *(lastSlash + 1) = L'\0'; 65 | } 66 | } 67 | 68 | inline HRESULT ReadDataFromFile(LPCWSTR filename, byte** data, UINT* size) 69 | { 70 | using namespace Microsoft::WRL; 71 | 72 | CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {}; 73 | extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); 74 | extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; 75 | extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; 76 | extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; 77 | extendedParams.lpSecurityAttributes = nullptr; 78 | extendedParams.hTemplateFile = nullptr; 79 | 80 | Wrappers::FileHandle file(CreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extendedParams)); 81 | if (file.Get() == INVALID_HANDLE_VALUE) 82 | { 83 | throw std::exception(); 84 | } 85 | 86 | FILE_STANDARD_INFO fileInfo = {}; 87 | if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) 88 | { 89 | throw std::exception(); 90 | } 91 | 92 | if (fileInfo.EndOfFile.HighPart != 0) 93 | { 94 | throw std::exception(); 95 | } 96 | 97 | *data = reinterpret_cast(malloc(fileInfo.EndOfFile.LowPart)); 98 | *size = fileInfo.EndOfFile.LowPart; 99 | 100 | if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr, nullptr)) 101 | { 102 | throw std::exception(); 103 | } 104 | 105 | return S_OK; 106 | } 107 | 108 | // Assign a name to the object to aid with debugging. 109 | #if defined(_DEBUG) || defined(DBG) 110 | inline void SetName(ID3D12Object* pObject, LPCWSTR name) 111 | { 112 | pObject->SetName(name); 113 | } 114 | inline void SetNameIndexed(ID3D12Object* pObject, LPCWSTR name, UINT index) 115 | { 116 | WCHAR fullName[50]; 117 | if (swprintf_s(fullName, L"%s[%u]", name, index) > 0) 118 | { 119 | pObject->SetName(fullName); 120 | } 121 | } 122 | #else 123 | inline void SetName(ID3D12Object*, LPCWSTR) 124 | { 125 | } 126 | inline void SetNameIndexed(ID3D12Object*, LPCWSTR, UINT) 127 | { 128 | } 129 | #endif 130 | 131 | // Naming helper for ComPtr. 132 | // Assigns the name of the variable as the name of the object. 133 | // The indexed variant will include the index in the name of the object. 134 | #define NAME_D3D12_OBJECT(x) SetName((x).Get(), L#x) 135 | #define NAME_D3D12_OBJECT_INDEXED(x, n) SetNameIndexed((x)[n].Get(), L#x, n) 136 | 137 | inline UINT CalculateConstantBufferByteSize(UINT byteSize) 138 | { 139 | // Constant buffer size is required to be aligned. 140 | return (byteSize + (D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1)) & ~(D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1); 141 | } 142 | 143 | #ifdef D3D_COMPILE_STANDARD_FILE_INCLUDE 144 | inline Microsoft::WRL::ComPtr CompileShader( 145 | const std::wstring& filename, 146 | const D3D_SHADER_MACRO* defines, 147 | const std::string& entrypoint, 148 | const std::string& target) 149 | { 150 | UINT compileFlags = 0; 151 | #if defined(_DEBUG) || defined(DBG) 152 | compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; 153 | #endif 154 | 155 | HRESULT hr; 156 | 157 | Microsoft::WRL::ComPtr byteCode = nullptr; 158 | Microsoft::WRL::ComPtr errors; 159 | hr = D3DCompileFromFile(filename.c_str(), defines, D3D_COMPILE_STANDARD_FILE_INCLUDE, 160 | entrypoint.c_str(), target.c_str(), compileFlags, 0, &byteCode, &errors); 161 | 162 | if (errors != nullptr) 163 | { 164 | OutputDebugStringA((char*)errors->GetBufferPointer()); 165 | } 166 | ThrowIfFailed(hr); 167 | 168 | return byteCode; 169 | } 170 | #endif 171 | 172 | // Resets all elements in a ComPtr array. 173 | template 174 | void ResetComPtrArray(T* comPtrArray) 175 | { 176 | for (auto &i : *comPtrArray) 177 | { 178 | i.Reset(); 179 | } 180 | } 181 | 182 | 183 | // Resets all elements in a unique_ptr array. 184 | template 185 | void ResetUniquePtrArray(T* uniquePtrArray) 186 | { 187 | for (auto &i : *uniquePtrArray) 188 | { 189 | i.reset(); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 4 | Copyright (c) 2015 Microsoft 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/Main.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "stdafx.h" 13 | #include "D3D12HelloNsightAftermath.h" 14 | 15 | _Use_decl_annotations_ 16 | int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) 17 | { 18 | D3D12HelloNsightAftermath sample(1280, 720, L"D3D12 Hello Nsight Aftermath"); 19 | return Win32Application::Run(&sample, hInstance, nCmdShow); 20 | } 21 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermath.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C:\NsightAftermathSDK 5 | $(NSIGHT_AFTERMATH_SDK)\include 6 | $(NSIGHT_AFTERMATH_SDK)\lib\x64 7 | 8 | 9 | 10 | $(NsightAftermathIncludeDir);%(AdditionalIncludeDirectories) 11 | 12 | 13 | $(NsightAftermathLibDir);%(AdditionalLibraryDirectories) 14 | GFSDK_AFTERMATH_Lib.x64.lib;%(AdditionalDependencies) 15 | 16 | 17 | 18 | 19 | GFSDK_AFTERMATH_Lib.x64.dll 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermathGpuCrashTracker.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #include "stdafx.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "NsightAftermathGpuCrashTracker.h" 33 | 34 | //********************************************************* 35 | // GpuCrashTracker implementation 36 | //********************************************************* 37 | 38 | GpuCrashTracker::GpuCrashTracker(const MarkerMap& markerMap) 39 | : m_initialized(false) 40 | , m_mutex() 41 | , m_shaderDebugInfo() 42 | , m_shaderDatabase() 43 | , m_markerMap(markerMap) 44 | { 45 | } 46 | 47 | GpuCrashTracker::~GpuCrashTracker() 48 | { 49 | // If initialized, disable GPU crash dumps 50 | if (m_initialized) 51 | { 52 | GFSDK_Aftermath_DisableGpuCrashDumps(); 53 | } 54 | } 55 | 56 | // Initialize the GPU Crash Dump Tracker 57 | void GpuCrashTracker::Initialize() 58 | { 59 | // Enable GPU crash dumps and set up the callbacks for crash dump notifications, 60 | // shader debug information notifications, and providing additional crash 61 | // dump description data.Only the crash dump callback is mandatory. The other two 62 | // callbacks are optional and can be omitted, by passing nullptr, if the corresponding 63 | // functionality is not used. 64 | // The DeferDebugInfoCallbacks flag enables caching of shader debug information data 65 | // in memory. If the flag is set, ShaderDebugInfoCallback will be called only 66 | // in the event of a crash, right before GpuCrashDumpCallback. If the flag is not set, 67 | // ShaderDebugInfoCallback will be called for every shader that is compiled. 68 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_EnableGpuCrashDumps( 69 | GFSDK_Aftermath_Version_API, 70 | GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_DX, 71 | GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks, // Let the Nsight Aftermath library cache shader debug information. 72 | GpuCrashDumpCallback, // Register callback for GPU crash dumps. 73 | ShaderDebugInfoCallback, // Register callback for shader debug information. 74 | CrashDumpDescriptionCallback, // Register callback for GPU crash dump description. 75 | ResolveMarkerCallback, // Register callback for resolving application-managed markers. 76 | this)); // Set the GpuCrashTracker object as user data for the above callbacks. 77 | 78 | m_initialized = true; 79 | } 80 | 81 | // Handler for GPU crash dump callbacks from Nsight Aftermath 82 | void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) 83 | { 84 | // Make sure only one thread at a time... 85 | std::lock_guard lock(m_mutex); 86 | 87 | // Write to file for later in-depth analysis with Nsight Graphics. 88 | WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); 89 | } 90 | 91 | // Handler for shader debug information callbacks 92 | void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) 93 | { 94 | // Make sure only one thread at a time... 95 | std::lock_guard lock(m_mutex); 96 | 97 | // Get shader debug information identifier 98 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; 99 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugInfoIdentifier( 100 | GFSDK_Aftermath_Version_API, 101 | pShaderDebugInfo, 102 | shaderDebugInfoSize, 103 | &identifier)); 104 | 105 | // Store information for decoding of GPU crash dumps with shader address mapping 106 | // from within the application. 107 | std::vector data((uint8_t*)pShaderDebugInfo, (uint8_t*)pShaderDebugInfo + shaderDebugInfoSize); 108 | m_shaderDebugInfo[identifier].swap(data); 109 | 110 | // Write to file for later in-depth analysis of crash dumps with Nsight Graphics 111 | WriteShaderDebugInformationToFile(identifier, pShaderDebugInfo, shaderDebugInfoSize); 112 | } 113 | 114 | // Handler for GPU crash dump description callbacks 115 | void GpuCrashTracker::OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription) 116 | { 117 | // Add some basic description about the crash. This is called after the GPU crash happens, but before 118 | // the actual GPU crash dump callback. The provided data is included in the crash dump and can be 119 | // retrieved using GFSDK_Aftermath_GpuCrashDump_GetDescription(). 120 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "D3D12HelloNsightAftermath"); 121 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion, "v1.0"); 122 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined, "This is a GPU crash dump example."); 123 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 1, "Engine State: Rendering."); 124 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 2, "More user-defined information..."); 125 | } 126 | 127 | // Handler for app-managed marker resolve callback 128 | void GpuCrashTracker::OnResolveMarker(const void* pMarkerData, const uint32_t markerDataSize, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize) 129 | { 130 | // Important: the pointer passed back via ppResolvedMarkerData must remain valid after this function returns 131 | // using references for all of the m_markerMap accesses ensures that the pointers refer to the persistent data 132 | for (auto& map : m_markerMap) 133 | { 134 | auto& foundMarker = map.find((uint64_t)pMarkerData); 135 | if (foundMarker != map.end()) 136 | { 137 | const std::string& foundMarkerData = foundMarker->second; 138 | // std::string::data() will return a valid pointer until the string is next modified 139 | // we don't modify the string after calling data() here, so the pointer should remain valid 140 | *ppResolvedMarkerData = (void*)foundMarkerData.data(); 141 | *pResolvedMarkerDataSize = (uint32_t)foundMarkerData.length(); 142 | return; 143 | } 144 | } 145 | } 146 | 147 | // Helper for writing a GPU crash dump to a file 148 | void GpuCrashTracker::WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) 149 | { 150 | // Create a GPU crash dump decoder object for the GPU crash dump. 151 | GFSDK_Aftermath_GpuCrashDump_Decoder decoder = {}; 152 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_CreateDecoder( 153 | GFSDK_Aftermath_Version_API, 154 | pGpuCrashDump, 155 | gpuCrashDumpSize, 156 | &decoder)); 157 | 158 | // Use the decoder object to read basic information, like application 159 | // name, PID, etc. from the GPU crash dump. 160 | GFSDK_Aftermath_GpuCrashDump_BaseInfo baseInfo = {}; 161 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetBaseInfo(decoder, &baseInfo)); 162 | 163 | // Use the decoder object to query the application name that was set 164 | // in the GPU crash dump description. 165 | uint32_t applicationNameLength = 0; 166 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize( 167 | decoder, 168 | GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, 169 | &applicationNameLength)); 170 | 171 | std::vector applicationName(applicationNameLength, '\0'); 172 | 173 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescription( 174 | decoder, 175 | GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, 176 | uint32_t(applicationName.size()), 177 | applicationName.data())); 178 | 179 | // Create a unique file name for writing the crash dump data to a file. 180 | // Note: due to an Nsight Aftermath bug (will be fixed in an upcoming 181 | // driver release) we may see redundant crash dumps. As a workaround, 182 | // attach a unique count to each generated file name. 183 | static int count = 0; 184 | const std::string baseFileName = 185 | std::string(applicationName.data()) 186 | + "-" 187 | + std::to_string(baseInfo.pid) 188 | + "-" 189 | + std::to_string(++count); 190 | 191 | // Write the crash dump data to a file using the .nv-gpudmp extension 192 | // registered with Nsight Graphics. 193 | const std::string crashDumpFileName = baseFileName + ".nv-gpudmp"; 194 | std::ofstream dumpFile(crashDumpFileName, std::ios::out | std::ios::binary); 195 | if (dumpFile) 196 | { 197 | dumpFile.write((const char*)pGpuCrashDump, gpuCrashDumpSize); 198 | dumpFile.close(); 199 | } 200 | 201 | // Decode the crash dump to a JSON string. 202 | // Step 1: Generate the JSON and get the size. 203 | uint32_t jsonSize = 0; 204 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GenerateJSON( 205 | decoder, 206 | GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO, 207 | GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE, 208 | ShaderDebugInfoLookupCallback, 209 | ShaderLookupCallback, 210 | ShaderSourceDebugInfoLookupCallback, 211 | this, 212 | &jsonSize)); 213 | // Step 2: Allocate a buffer and fetch the generated JSON. 214 | std::vector json(jsonSize); 215 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetJSON( 216 | decoder, 217 | uint32_t(json.size()), 218 | json.data())); 219 | 220 | // Write the crash dump data as JSON to a file. 221 | const std::string jsonFileName = crashDumpFileName + ".json"; 222 | std::ofstream jsonFile(jsonFileName, std::ios::out | std::ios::binary); 223 | if (jsonFile) 224 | { 225 | // Write the JSON to the file (excluding string termination) 226 | jsonFile.write(json.data(), json.size() - 1); 227 | jsonFile.close(); 228 | } 229 | 230 | // Destroy the GPU crash dump decoder object. 231 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder)); 232 | } 233 | 234 | // Helper for writing shader debug information to a file 235 | void GpuCrashTracker::WriteShaderDebugInformationToFile( 236 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, 237 | const void* pShaderDebugInfo, 238 | const uint32_t shaderDebugInfoSize) 239 | { 240 | // Create a unique file name. 241 | const std::string filePath = "shader-" + std::to_string(identifier) + ".nvdbg"; 242 | 243 | std::ofstream f(filePath, std::ios::out | std::ios::binary); 244 | if (f) 245 | { 246 | f.write((const char*)pShaderDebugInfo, shaderDebugInfoSize); 247 | } 248 | } 249 | 250 | // Handler for shader debug information lookup callbacks. 251 | // This is used by the JSON decoder for mapping shader instruction 252 | // addresses to DXIL lines or HLSl source lines. 253 | void GpuCrashTracker::OnShaderDebugInfoLookup( 254 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, 255 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const 256 | { 257 | // Search the list of shader debug information blobs received earlier. 258 | auto i_debugInfo = m_shaderDebugInfo.find(identifier); 259 | if (i_debugInfo == m_shaderDebugInfo.end()) 260 | { 261 | // Early exit, nothing found. No need to call setShaderDebugInfo. 262 | return; 263 | } 264 | 265 | // Let the GPU crash dump decoder know about the shader debug information 266 | // that was found. 267 | setShaderDebugInfo(i_debugInfo->second.data(), uint32_t(i_debugInfo->second.size())); 268 | } 269 | 270 | // Handler for shader lookup callbacks. 271 | // This is used by the JSON decoder for mapping shader instruction 272 | // addresses to DXIL lines or HLSL source lines. 273 | // NOTE: If the application loads stripped shader binaries (-Qstrip_debug), 274 | // Aftermath will require access to both the stripped and the not stripped 275 | // shader binaries. 276 | void GpuCrashTracker::OnShaderLookup( 277 | const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, 278 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const 279 | { 280 | // Find shader binary data for the shader hash in the shader database. 281 | std::vector shaderBinary; 282 | if (!m_shaderDatabase.FindShaderBinary(shaderHash, shaderBinary)) 283 | { 284 | // Early exit, nothing found. No need to call setShaderBinary. 285 | return; 286 | } 287 | 288 | // Let the GPU crash dump decoder know about the shader data 289 | // that was found. 290 | setShaderBinary(shaderBinary.data(), uint32_t(shaderBinary.size())); 291 | } 292 | 293 | // Handler for shader source debug info lookup callbacks. 294 | // This is used by the JSON decoder for mapping shader instruction addresses to 295 | // HLSL source lines, if the shaders used by the application were compiled with 296 | // separate debug info data files. 297 | void GpuCrashTracker::OnShaderSourceDebugInfoLookup( 298 | const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, 299 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const 300 | { 301 | // Find source debug info for the shader DebugName in the shader database. 302 | std::vector sourceDebugInfo; 303 | if (!m_shaderDatabase.FindSourceShaderDebugData(shaderDebugName, sourceDebugInfo)) 304 | { 305 | // Early exit, nothing found. No need to call setShaderBinary. 306 | return; 307 | } 308 | 309 | // Let the GPU crash dump decoder know about the shader debug data that was 310 | // found. 311 | setShaderBinary(sourceDebugInfo.data(), uint32_t(sourceDebugInfo.size())); 312 | } 313 | 314 | // Static callback wrapper for OnCrashDump 315 | void GpuCrashTracker::GpuCrashDumpCallback( 316 | const void* pGpuCrashDump, 317 | const uint32_t gpuCrashDumpSize, 318 | void* pUserData) 319 | { 320 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 321 | pGpuCrashTracker->OnCrashDump(pGpuCrashDump, gpuCrashDumpSize); 322 | } 323 | 324 | // Static callback wrapper for OnShaderDebugInfo 325 | void GpuCrashTracker::ShaderDebugInfoCallback( 326 | const void* pShaderDebugInfo, 327 | const uint32_t shaderDebugInfoSize, 328 | void* pUserData) 329 | { 330 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 331 | pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize); 332 | } 333 | 334 | // Static callback wrapper for OnDescription 335 | void GpuCrashTracker::CrashDumpDescriptionCallback( 336 | PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, 337 | void* pUserData) 338 | { 339 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 340 | pGpuCrashTracker->OnDescription(addDescription); 341 | } 342 | 343 | // Static callback wrapper for OnResolveMarker 344 | void GpuCrashTracker::ResolveMarkerCallback( 345 | const void* pMarkerData, 346 | const uint32_t markerDataSize, 347 | void* pUserData, 348 | void** ppResolvedMarkerData, 349 | uint32_t* pResolvedMarkerDataSize) 350 | { 351 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 352 | pGpuCrashTracker->OnResolveMarker(pMarkerData, markerDataSize, ppResolvedMarkerData, pResolvedMarkerDataSize); 353 | } 354 | 355 | // Static callback wrapper for OnShaderDebugInfoLookup 356 | void GpuCrashTracker::ShaderDebugInfoLookupCallback( 357 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, 358 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, 359 | void* pUserData) 360 | { 361 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 362 | pGpuCrashTracker->OnShaderDebugInfoLookup(*pIdentifier, setShaderDebugInfo); 363 | } 364 | 365 | // Static callback wrapper for OnShaderLookup 366 | void GpuCrashTracker::ShaderLookupCallback( 367 | const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, 368 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 369 | void* pUserData) 370 | { 371 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 372 | pGpuCrashTracker->OnShaderLookup(*pShaderHash, setShaderBinary); 373 | } 374 | 375 | // Static callback wrapper for OnShaderSourceDebugInfoLookup 376 | void GpuCrashTracker::ShaderSourceDebugInfoLookupCallback( 377 | const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, 378 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 379 | void* pUserData) 380 | { 381 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 382 | pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary); 383 | } 384 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermathGpuCrashTracker.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include "NsightAftermathHelpers.h" 31 | #include "NsightAftermathShaderDatabase.h" 32 | 33 | //********************************************************* 34 | // Implements GPU crash dump tracking using the Nsight 35 | // Aftermath API. 36 | // 37 | class GpuCrashTracker 38 | { 39 | public: 40 | // keep four frames worth of marker history 41 | const static UINT c_markerFrameHistory = 4; 42 | typedef std::array, c_markerFrameHistory> MarkerMap; 43 | 44 | GpuCrashTracker(const MarkerMap& markerMap); 45 | ~GpuCrashTracker(); 46 | 47 | // Initialize the GPU crash dump tracker. 48 | void Initialize(); 49 | 50 | private: 51 | 52 | //********************************************************* 53 | // Callback handlers for GPU crash dumps and related data. 54 | // 55 | 56 | // Handler for GPU crash dump callbacks. 57 | void OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); 58 | 59 | // Handler for shader debug information callbacks. 60 | void OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize); 61 | 62 | // Handler for GPU crash dump description callbacks. 63 | void OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription); 64 | 65 | // Handler for app-managed marker resolve callback 66 | void OnResolveMarker(const void* pMarkerData, const uint32_t markerDataSize, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize); 67 | 68 | //********************************************************* 69 | // Helpers for writing a GPU crash dump and debug information 70 | // data to files. 71 | // 72 | 73 | // Helper for writing a GPU crash dump to a file. 74 | void WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); 75 | 76 | // Helper for writing shader debug information to a file 77 | void WriteShaderDebugInformationToFile( 78 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, 79 | const void* pShaderDebugInfo, 80 | const uint32_t shaderDebugInfoSize); 81 | 82 | //********************************************************* 83 | // Helpers for decoding GPU crash dump to JSON. 84 | // 85 | 86 | // Handler for shader debug info lookup callbacks. 87 | void OnShaderDebugInfoLookup( 88 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, 89 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const; 90 | 91 | // Handler for shader lookup callbacks. 92 | void OnShaderLookup( 93 | const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, 94 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const; 95 | 96 | // Handler for shader source debug info lookup callbacks. 97 | void OnShaderSourceDebugInfoLookup( 98 | const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, 99 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const; 100 | 101 | //********************************************************* 102 | // Static callback wrappers. 103 | // 104 | 105 | // GPU crash dump callback. 106 | static void GpuCrashDumpCallback( 107 | const void* pGpuCrashDump, 108 | const uint32_t gpuCrashDumpSize, 109 | void* pUserData); 110 | 111 | // Shader debug information callback. 112 | static void ShaderDebugInfoCallback( 113 | const void* pShaderDebugInfo, 114 | const uint32_t shaderDebugInfoSize, 115 | void* pUserData); 116 | 117 | // GPU crash dump description callback. 118 | static void CrashDumpDescriptionCallback( 119 | PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, 120 | void* pUserData); 121 | 122 | // App-managed marker resolve callback 123 | static void ResolveMarkerCallback( 124 | const void* pMarkerData, 125 | const uint32_t markerDataSize, 126 | void* pUserData, 127 | void** ppResolvedMarkerData, 128 | uint32_t* pResolvedMarkerDataSize 129 | ); 130 | 131 | // Shader debug information lookup callback. 132 | static void ShaderDebugInfoLookupCallback( 133 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, 134 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, 135 | void* pUserData); 136 | 137 | // Shader lookup callback. 138 | static void ShaderLookupCallback( 139 | const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, 140 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 141 | void* pUserData); 142 | 143 | // Shader source debug info lookup callback. 144 | static void ShaderSourceDebugInfoLookupCallback( 145 | const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, 146 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 147 | void* pUserData); 148 | 149 | //********************************************************* 150 | // GPU crash tracker state. 151 | // 152 | 153 | // Is the GPU crash dump tracker initialized? 154 | bool m_initialized; 155 | 156 | // For thread-safe access of GPU crash tracker state. 157 | mutable std::mutex m_mutex; 158 | 159 | // List of Shader Debug Information by ShaderDebugInfoIdentifier. 160 | std::map> m_shaderDebugInfo; 161 | 162 | // The mock shader database. 163 | ShaderDatabase m_shaderDatabase; 164 | 165 | // App-managed marker tracking 166 | const MarkerMap& m_markerMap; 167 | }; 168 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermathHelpers.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "GFSDK_Aftermath.h" 32 | #include "GFSDK_Aftermath_GpuCrashDump.h" 33 | #include "GFSDK_Aftermath_GpuCrashDumpDecoding.h" 34 | 35 | //********************************************************* 36 | // Some std::to_string overloads for some Nsight Aftermath 37 | // API types. 38 | // 39 | 40 | namespace std 41 | { 42 | template 43 | inline std::string to_hex_string(T n) 44 | { 45 | std::stringstream stream; 46 | stream << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex << n; 47 | return stream.str(); 48 | } 49 | 50 | inline std::string to_string(GFSDK_Aftermath_Result result) 51 | { 52 | return std::string("0x") + to_hex_string(static_cast(result)); 53 | } 54 | 55 | inline std::string to_string(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier) 56 | { 57 | return to_hex_string(identifier.id[0]) + "-" + to_hex_string(identifier.id[1]); 58 | } 59 | 60 | inline std::string to_string(const GFSDK_Aftermath_ShaderBinaryHash& hash) 61 | { 62 | return to_hex_string(hash.hash); 63 | } 64 | } // namespace std 65 | 66 | //********************************************************* 67 | // Helper for comparing shader hashes and debug info identifier. 68 | // 69 | 70 | // Helper for comparing GFSDK_Aftermath_ShaderDebugInfoIdentifier. 71 | inline bool operator<(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& lhs, const GFSDK_Aftermath_ShaderDebugInfoIdentifier& rhs) 72 | { 73 | if (lhs.id[0] == rhs.id[0]) 74 | { 75 | return lhs.id[1] < rhs.id[1]; 76 | } 77 | return lhs.id[0] < rhs.id[0]; 78 | } 79 | 80 | // Helper for comparing GFSDK_Aftermath_ShaderBinaryHash. 81 | inline bool operator<(const GFSDK_Aftermath_ShaderBinaryHash& lhs, const GFSDK_Aftermath_ShaderBinaryHash& rhs) 82 | { 83 | return lhs.hash < rhs.hash; 84 | } 85 | 86 | // Helper for comparing GFSDK_Aftermath_ShaderDebugName. 87 | inline bool operator<(const GFSDK_Aftermath_ShaderDebugName& lhs, const GFSDK_Aftermath_ShaderDebugName& rhs) 88 | { 89 | return strncmp(lhs.name, rhs.name, sizeof(lhs.name)) < 0; 90 | } 91 | 92 | //********************************************************* 93 | // Helper for checking Nsight Aftermath failures. 94 | // 95 | 96 | // Exception for Nsight Aftermath failures 97 | class AftermathException : public std::runtime_error 98 | { 99 | public: 100 | AftermathException(GFSDK_Aftermath_Result result) 101 | : std::runtime_error(GetErrorMessage(result)) 102 | , m_result(result) 103 | { 104 | } 105 | 106 | AftermathException Error() const 107 | { 108 | return m_result; 109 | } 110 | 111 | static std::string GetErrorMessage(GFSDK_Aftermath_Result result) 112 | { 113 | switch (result) 114 | { 115 | case GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported: 116 | return "Unsupported driver version - requires an NVIDIA R495 display driver or newer."; 117 | case GFSDK_Aftermath_Result_FAIL_D3dDllInterceptionNotSupported: 118 | return "Aftermath is incompatible with D3D API interception, such as PIX or Nsight Graphics."; 119 | default: 120 | return "Aftermath Error 0x" + std::to_hex_string(result); 121 | } 122 | } 123 | 124 | private: 125 | const GFSDK_Aftermath_Result m_result; 126 | }; 127 | 128 | // Helper macro for checking Nsight Aftermath results and throwing exception 129 | // in case of a failure. 130 | #define AFTERMATH_CHECK_ERROR(FC) \ 131 | [&]() { \ 132 | GFSDK_Aftermath_Result _result = FC; \ 133 | if (!GFSDK_Aftermath_SUCCEED(_result)) \ 134 | { \ 135 | MessageBoxA(0, AftermathException::GetErrorMessage(_result).c_str(), "Aftermath Error", MB_OK); \ 136 | throw AftermathException(_result); \ 137 | } \ 138 | }() 139 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermathShaderDatabase.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #include "stdafx.h" 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include "NsightAftermathShaderDatabase.h" 33 | 34 | //********************************************************* 35 | // ShaderDatabase implementation 36 | //********************************************************* 37 | 38 | ShaderDatabase::ShaderDatabase() 39 | : m_shaderBinaries() 40 | , m_sourceShaderDebugData() 41 | { 42 | // Add shader binaries to database 43 | const char* shaderBinaryDirs[] = { SHADERS_DIR, "Shaders" }; 44 | for (size_t n = 0; n < sizeof(shaderBinaryDirs) / sizeof(const char*); ++n) 45 | { 46 | const std::string filePattern = std::string(shaderBinaryDirs[n]) + "/*.cso"; 47 | 48 | WIN32_FIND_DATAA findData; 49 | HANDLE hFind = FindFirstFileA(filePattern.c_str(), &findData); 50 | if (hFind != INVALID_HANDLE_VALUE) 51 | { 52 | do 53 | { 54 | const std::string filePath = std::string(shaderBinaryDirs[n]) + "/" + findData.cFileName; 55 | AddShaderBinary(filePath.c_str()); 56 | } while (FindNextFileA(hFind, &findData) != 0); 57 | FindClose(hFind); 58 | } 59 | } 60 | 61 | // Add shader debug data to database 62 | const char* shaderDebugDataDirs[] = { SHADERS_DIR, "Shaders" }; 63 | const char* shaderDebugDataFileExts[] = { ".lld", ".pdb" }; 64 | for (size_t n = 0; n < sizeof(shaderDebugDataDirs) / sizeof(const char*); ++n) 65 | { 66 | for (size_t m = 0; m < sizeof(shaderDebugDataFileExts) / sizeof(const char*); ++m) 67 | { 68 | const std::string filePattern = std::string(shaderDebugDataDirs[n]) + "/*" + shaderDebugDataFileExts[m]; 69 | 70 | WIN32_FIND_DATAA findData; 71 | HANDLE hFind = FindFirstFileA(filePattern.c_str(), &findData); 72 | if (hFind != INVALID_HANDLE_VALUE) 73 | { 74 | do 75 | { 76 | const std::string filePath = std::string(shaderDebugDataDirs[n]) + "/" + findData.cFileName; 77 | AddSourceShaderDebugData(filePath.c_str(), findData.cFileName); 78 | } while (FindNextFileA(hFind, &findData) != 0); 79 | FindClose(hFind); 80 | } 81 | } 82 | } 83 | } 84 | 85 | ShaderDatabase::~ShaderDatabase() 86 | { 87 | } 88 | 89 | bool ShaderDatabase::ReadFile(const char* filename, std::vector& data) 90 | { 91 | std::ifstream fs(filename, std::ios::in | std::ios::binary); 92 | if (!fs) 93 | { 94 | return false; 95 | } 96 | 97 | fs.seekg(0, std::ios::end); 98 | data.resize(fs.tellg()); 99 | fs.seekg(0, std::ios::beg); 100 | fs.read(reinterpret_cast(data.data()), data.size()); 101 | fs.close(); 102 | 103 | return true; 104 | } 105 | 106 | void ShaderDatabase::AddShaderBinary(const char* filePath) 107 | { 108 | // Read the shader bytecode from the file 109 | std::vector data; 110 | if (!ReadFile(filePath, data)) 111 | { 112 | return; 113 | } 114 | 115 | // Create shader hashes for the shader bytecode 116 | const D3D12_SHADER_BYTECODE shader{ data.data(), data.size() }; 117 | GFSDK_Aftermath_ShaderBinaryHash shaderHash; 118 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderHash( 119 | GFSDK_Aftermath_Version_API, 120 | &shader, 121 | &shaderHash)); 122 | 123 | // Store the data for shader instruction address mapping when decoding GPU crash dumps. 124 | // cf. FindShaderBinary() 125 | m_shaderBinaries[shaderHash].swap(data); 126 | } 127 | 128 | void ShaderDatabase::AddSourceShaderDebugData(const char* filePath, const char* fileName) 129 | { 130 | // Read the shader debug data from the file 131 | std::vector data; 132 | if (!ReadFile(filePath, data)) 133 | { 134 | return; 135 | } 136 | 137 | // Populate shader debug name. 138 | // The shaders used in this sample are compiled with compiler-generated debug data 139 | // file names. That means the debug data file's name matches the corresponding 140 | // shader's DebugName. 141 | // If shaders are built with user-defined debug data file names, the shader database 142 | // must maintain a mapping between the shader DebugName (queried from the shader 143 | // binary with GFSDK_Aftermath_GetShaderDebugName()) and the name of the file 144 | // containing the corresponding debug data. 145 | // Please see the documentation of GFSDK_Aftermath_GpuCrashDump_GenerateJSON() for 146 | // additional information. 147 | GFSDK_Aftermath_ShaderDebugName debugName; 148 | strncpy_s(debugName.name, fileName, sizeof(debugName.name) - 1); 149 | 150 | // Store the data for shader instruction address mapping when decoding GPU crash dumps. 151 | // cf. FindSourceShaderDebugData() 152 | m_sourceShaderDebugData[debugName].swap(data); 153 | } 154 | 155 | // Find a shader bytecode binary by shader hash. 156 | bool ShaderDatabase::FindShaderBinary(const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, std::vector& shader) const 157 | { 158 | // Find shader binary data for the shader hash 159 | auto i_shader = m_shaderBinaries.find(shaderHash); 160 | if (i_shader == m_shaderBinaries.end()) 161 | { 162 | // Nothing found. 163 | return false; 164 | } 165 | 166 | shader = i_shader->second; 167 | return true; 168 | } 169 | 170 | // Find a source shader debug info by shader debug name generated by the DXC compiler. 171 | bool ShaderDatabase::FindSourceShaderDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& debugData) const 172 | { 173 | // Find shader debug data for the shader debug name. 174 | auto i_data = m_sourceShaderDebugData.find(shaderDebugName); 175 | if (i_data == m_sourceShaderDebugData.end()) 176 | { 177 | // Nothing found. 178 | return false; 179 | } 180 | 181 | debugData = i_data->second; 182 | return true; 183 | } 184 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/NsightAftermathShaderDatabase.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include "NsightAftermathHelpers.h" 31 | 32 | //********************************************************* 33 | // Implements a very simple shader database to help demonstrate 34 | // how to use the Nsight Aftermath GPU crash dump decoder API. 35 | // 36 | // In a real world scenario this would be part of an offline 37 | // analysis tool. This is for demonstration purposes only! 38 | // 39 | class ShaderDatabase 40 | { 41 | public: 42 | ShaderDatabase(); 43 | ~ShaderDatabase(); 44 | 45 | // Find a shader bytecode binary by shader hash. 46 | bool FindShaderBinary(const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, std::vector& shader) const; 47 | 48 | // Find a source shader debug info by shader debug name generated by the DXC compiler. 49 | bool FindSourceShaderDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& debugData) const; 50 | 51 | private: 52 | 53 | void AddShaderBinary(const char* filePath); 54 | void AddSourceShaderDebugData(const char* filePath, const char* fileName); 55 | 56 | static bool ReadFile(const char* filename, std::vector& data); 57 | 58 | // List of shader binaries by ShaderBinaryHash. 59 | std::map> m_shaderBinaries; 60 | 61 | // List of available source shader debug information. 62 | std::map> m_sourceShaderDebugData; 63 | }; 64 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/PixelShader.hlsl: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "Shader.hlsli" 13 | 14 | float4 PSMain(PSInput input) : SV_TARGET 15 | { 16 | return input.color; 17 | } 18 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/README.md: -------------------------------------------------------------------------------- 1 | # Example for Nsight Aftermath GPU Crash Dump User Application Integration 2 | 3 | This sample source code shows how to integrate Nsight Aftermath GPU crash dump 4 | collection and decoding into a D3D12 application. 5 | 6 | ## Requirements 7 | 8 | * [Visual Studio 2022](https://www.visualstudio.com/) 9 | * [Windows SDK 10.0.22621.755 (October 2022 Update) or newer](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk) 10 | * [Nsight Aftermath SDK 2023.2 or newer](https://developer.nvidia.com/nsight-aftermath) 11 | * [NVIDIA R550 driver (or newer)](https://www.nvidia.com/Download/index.aspx?lang=en-us) 12 | 13 | ## Source Organization 14 | 15 | * `D3D12HelloNsightAftermath.cpp` 16 | * Main implementation file (D3D12 device creation, resource creation, 17 | rendering). 18 | * All additions for Nsight Aftermath code instrumentation are guarded with 19 | `#if USE_NSIGHT_AFTERMATH`. To disable this instrumentation, ensure 20 | `USE_NSIGHT_AFTERMATH` is defined as `0` or is undefined. 21 | * `NsightAftermathGpuCrashTracker.cpp` 22 | * Implements a simple GPU crash dump tracker showing the use of the Nsight 23 | Aftermath API for collecting and decoding GPU crash dumps. 24 | * `NsightAftermathShaderDatabase.cpp` 25 | * Implements a very basic shader database as an example of how to provide 26 | shader binary data and shader debug data for shader instruction address 27 | mapping when decoding crash dumps. 28 | 29 | NOTE: this sample code implements GPU crash dump collection and decoding in a 30 | single application, but this is not the typical use case. Rather, users will 31 | typically split this into a GPU crash dump collection phase, integrated into the 32 | graphics application, and an offline decoding phase, implemented as an offline 33 | GPU crash dump analysis tool. 34 | 35 | ## Building the Sample 36 | 37 | * Set the `NSIGHT_AFTERMATH_SDK` environment variable or edit `NsightAftermath.props` 38 | in a text editor to match the installation location of your installed copy of 39 | the Nsight Aftermath SDK. 40 | * Open D3D12HelloNsightAftermath.vcxproj in Visual Studio. 41 | * Build -> Build Solution. 42 | 43 | ## Running the Sample 44 | 45 | * Run `D3D12HelloNsightAftermath.exe`. 46 | * The application will render a simple animated triangle and will hang/TDR after 47 | a few seconds. 48 | * A GPU crash dump file (D3D12HelloNsightAftermath--.nv-gpudmp), 49 | a text file containing the GPU crash dump data decoded into JSON 50 | (`D3D12HelloNsightAftermath--.nv-gpudmp.json`) and a shader 51 | debug information file (`shader-.nvdbg`) will be created in the 52 | application's working directory. 53 | * Open the JSON file to inspect the data captured for the crash or use 54 | [Nsight Graphics](https://developer.nvidia.com/nsight-graphics) to open 55 | the GPU crash dump file. 56 | 57 | ## Copyright and Licenses 58 | 59 | cf. LICENSE file. 60 | 61 | This Code is based upon the HelloConstBuffers sample from https://github.com/microsoft/DirectX-Graphics-Samples (Copyright (c) 2015 Microsoft). 62 | 63 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/Shader.hlsli: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #ifndef SHADER_HLSLI 13 | #define SHADER_HLSLI 14 | 15 | cbuffer SceneConstantBuffer : register(b0) 16 | { 17 | float4 offset; 18 | }; 19 | 20 | struct PSInput 21 | { 22 | float4 position : SV_POSITION; 23 | float4 color : COLOR; 24 | }; 25 | 26 | #endif // SHADER_HLSLI 27 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/VertexShader.hlsl: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "Shader.hlsli" 13 | 14 | PSInput VSMain(float4 position : POSITION, float4 color : COLOR) 15 | { 16 | PSInput result; 17 | 18 | result.position = position + offset; 19 | result.color = color; 20 | 21 | // Apply some location-based color modifications (with a bug causing a shader hang) 22 | float alpha = color.x; 23 | while (alpha > 0.0) 24 | { 25 | alpha -= offset.x; 26 | result.color *= (1.0 - 0.1*alpha); 27 | } 28 | 29 | return result; 30 | } 31 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/Win32Application.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "stdafx.h" 13 | #include "Win32Application.h" 14 | 15 | HWND Win32Application::m_hwnd = nullptr; 16 | 17 | int Win32Application::Run(DXSample* pSample, HINSTANCE hInstance, int nCmdShow) 18 | { 19 | // Parse the command line parameters 20 | int argc; 21 | LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); 22 | pSample->ParseCommandLineArgs(argv, argc); 23 | LocalFree(argv); 24 | 25 | // Initialize the window class. 26 | WNDCLASSEX windowClass = { 0 }; 27 | windowClass.cbSize = sizeof(WNDCLASSEX); 28 | windowClass.style = CS_HREDRAW | CS_VREDRAW; 29 | windowClass.lpfnWndProc = WindowProc; 30 | windowClass.hInstance = hInstance; 31 | windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); 32 | windowClass.lpszClassName = L"DXSampleClass"; 33 | RegisterClassEx(&windowClass); 34 | 35 | RECT windowRect = { 0, 0, static_cast(pSample->GetWidth()), static_cast(pSample->GetHeight()) }; 36 | AdjustWindowRect(&windowRect, WS_OVERLAPPEDWINDOW, FALSE); 37 | 38 | // Create the window and store a handle to it. 39 | m_hwnd = CreateWindow( 40 | windowClass.lpszClassName, 41 | pSample->GetTitle(), 42 | WS_OVERLAPPEDWINDOW, 43 | CW_USEDEFAULT, 44 | CW_USEDEFAULT, 45 | windowRect.right - windowRect.left, 46 | windowRect.bottom - windowRect.top, 47 | nullptr, // We have no parent window. 48 | nullptr, // We aren't using menus. 49 | hInstance, 50 | pSample); 51 | 52 | // Initialize the sample. OnInit is defined in each child-implementation of DXSample. 53 | pSample->OnInit(); 54 | 55 | ShowWindow(m_hwnd, nCmdShow); 56 | 57 | // Main sample loop. 58 | MSG msg = {}; 59 | while (msg.message != WM_QUIT) 60 | { 61 | // Process any messages in the queue. 62 | if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 63 | { 64 | TranslateMessage(&msg); 65 | DispatchMessage(&msg); 66 | } 67 | } 68 | 69 | pSample->OnDestroy(); 70 | 71 | // Return this part of the WM_QUIT message to Windows. 72 | return static_cast(msg.wParam); 73 | } 74 | 75 | // Main message handler for the sample. 76 | LRESULT CALLBACK Win32Application::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 77 | { 78 | DXSample* pSample = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); 79 | 80 | switch (message) 81 | { 82 | case WM_CREATE: 83 | { 84 | // Save the DXSample* passed in to CreateWindow. 85 | LPCREATESTRUCT pCreateStruct = reinterpret_cast(lParam); 86 | SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast(pCreateStruct->lpCreateParams)); 87 | } 88 | return 0; 89 | 90 | case WM_KEYDOWN: 91 | if (pSample) 92 | { 93 | pSample->OnKeyDown(static_cast(wParam)); 94 | } 95 | return 0; 96 | 97 | case WM_KEYUP: 98 | if (pSample) 99 | { 100 | pSample->OnKeyUp(static_cast(wParam)); 101 | } 102 | return 0; 103 | 104 | case WM_PAINT: 105 | if (pSample) 106 | { 107 | pSample->OnUpdate(); 108 | pSample->OnRender(); 109 | } 110 | return 0; 111 | 112 | case WM_DESTROY: 113 | PostQuitMessage(0); 114 | return 0; 115 | } 116 | 117 | // Handle any messages the switch statement didn't. 118 | return DefWindowProc(hWnd, message, wParam, lParam); 119 | } 120 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/Win32Application.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #include "DXSample.h" 15 | 16 | class DXSample; 17 | 18 | class Win32Application 19 | { 20 | public: 21 | static int Run(DXSample* pSample, HINSTANCE hInstance, int nCmdShow); 22 | static HWND GetHwnd() { return m_hwnd; } 23 | 24 | protected: 25 | static LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 26 | 27 | private: 28 | static HWND m_hwnd; 29 | }; 30 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/stdafx.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "stdafx.h" 13 | -------------------------------------------------------------------------------- /D3D12HelloNsightAftermath/stdafx.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | // stdafx.h : include file for standard system include files, 13 | // or project specific include files that are used frequently, but 14 | // are changed infrequently. 15 | 16 | #pragma once 17 | 18 | #ifndef WIN32_LEAN_AND_MEAN 19 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers. 20 | #endif 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "d3dx12.h" 29 | 30 | #include 31 | #include 32 | #include 33 | -------------------------------------------------------------------------------- /GpuCrashDump/D3D12HelloNsightAftermath-12252-1.nv-gpudmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/nsight-aftermath-samples/c46b2f581c3c93c56891dce99ea793e013171db6/GpuCrashDump/D3D12HelloNsightAftermath-12252-1.nv-gpudmp -------------------------------------------------------------------------------- /GpuCrashDump/Extras/D3D12HelloNsightAftermath.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/nsight-aftermath-samples/c46b2f581c3c93c56891dce99ea793e013171db6/GpuCrashDump/Extras/D3D12HelloNsightAftermath.pdb -------------------------------------------------------------------------------- /GpuCrashDump/Extras/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. 4 | Copyright (c) 2015 Microsoft 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /GpuCrashDump/Extras/Shaders/PixelShader.cso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/nsight-aftermath-samples/c46b2f581c3c93c56891dce99ea793e013171db6/GpuCrashDump/Extras/Shaders/PixelShader.cso -------------------------------------------------------------------------------- /GpuCrashDump/Extras/Shaders/VertexShader.cso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/nsight-aftermath-samples/c46b2f581c3c93c56891dce99ea793e013171db6/GpuCrashDump/Extras/Shaders/VertexShader.cso -------------------------------------------------------------------------------- /GpuCrashDump/Extras/SourceShaders/PixelShader.hlsl: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "Shader.hlsli" 13 | 14 | float4 PSMain(PSInput input) : SV_TARGET 15 | { 16 | return input.color; 17 | } 18 | -------------------------------------------------------------------------------- /GpuCrashDump/Extras/SourceShaders/Shader.hlsli: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #ifndef SHADER_HLSLI 13 | #define SHADER_HLSLI 14 | 15 | cbuffer SceneConstantBuffer : register(b0) 16 | { 17 | float4 offset; 18 | }; 19 | 20 | struct PSInput 21 | { 22 | float4 position : SV_POSITION; 23 | float4 color : COLOR; 24 | }; 25 | 26 | #endif // SHADER_HLSLI 27 | -------------------------------------------------------------------------------- /GpuCrashDump/Extras/SourceShaders/VertexShader.hlsl: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "Shader.hlsli" 13 | 14 | PSInput VSMain(float4 position : POSITION, float4 color : COLOR) 15 | { 16 | PSInput result; 17 | 18 | result.position = position + offset; 19 | result.color = color; 20 | 21 | // Apply some location-based color modifications (with a bug causing a shader hang) 22 | float alpha = color.x; 23 | while (alpha > 0.0) 24 | { 25 | alpha -= offset.x; 26 | result.color *= (1.0 - 0.1*alpha); 27 | } 28 | 29 | return result; 30 | } 31 | -------------------------------------------------------------------------------- /GpuCrashDump/README.md: -------------------------------------------------------------------------------- 1 | # Example Nsight Aftermath GPU Crash Dump 2 | 3 | This directory contains an example GPU crash dump captured with the 4 | D3D12HelloNsightAftermath example application. This GPU crash dump captures a 5 | TDR timeout due to a very long running vertex shader. 6 | 7 | The sample used for capturing the GPU crash dump is a very basic D3D12 8 | application that renders only a single triangle. When inspecting the dump you 9 | will notice only a single vertex shader warp in flight when the GPU hang 10 | occured. This is because any fragment work from previous frames has already 11 | retired from the shader units by the time the hang is detected and processed by 12 | the CPU. In real applications, there will usually be many more active warps 13 | listed, some executing warps without any problems or exceptions, and some 14 | indicating the faulting warps. 15 | 16 | ## Files 17 | 18 | * D3D12HelloNsightAftermath-12252-1.nv-gpudmp -- the GPU crash dump file. 19 | * shader-59339c1ea8934740-00000210749de540.nvdbg -- the debug information file 20 | for the shader referenced in the GPU crash dump. 21 | * Extras\D3D12HelloNsightAftermath.pdb -- the Program Data Base file necessary 22 | for resolving the call stacks captured in the GPU crash dump. 23 | * Extras\Shaders -- shader object files required to resolve to the shader source line. 24 | * Extras\SourceShaders -- shader source files required to show the shader source. 25 | 26 | ## Reading the GPU Crash Dump 27 | 28 | * Install [Nsight Graphics](https://developer.nvidia.com/nsight-graphics) 29 | * Run Nsight Graphics from the start menu 30 | * Open the Gpu Crash Dump Options dialog (`Tools->Options...->GPU Crash Dump`). 31 | * In `Shader Debug Info paths` add the file path that contains the 32 | shader-59339c1ea8934740-00000210749de540.nvdbg file. 33 | * In `Shader Source Paths` add the file path to Extras\SourceShaders. 34 | * In `Shader Object Paths` add the file path to Extras\Shaders. 35 | * In `PDB Search Paths` add the file path that contains 36 | Extras\D3D12HelloNsightAftermath.pdb. 37 | * Close the dialog by clicking `OK`. 38 | * Open the D3D12HelloNsightAftermath-12252-1.nv-gpudmp file 39 | (`File->Open Files...`). 40 | * Detailed information on how to use Nsight Graphics to inspect Nsight 41 | Aftermath GPU crash dumps can be found in the 42 | [Nsight Graphics User Guide](https://docs.nvidia.com/nsight-graphics/UserGuide/index.html#gcd_inspector). 43 | 44 | -------------------------------------------------------------------------------- /GpuCrashDump/shader-59339c1ea8934740-00000210749de540.nvdbg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/nsight-aftermath-samples/c46b2f581c3c93c56891dce99ea793e013171db6/GpuCrashDump/shader-59339c1ea8934740-00000210749de540.nvdbg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nsight Aftermath SDK Samples 2 | 3 | This repository contains samples for the [Nsight Aftermath SDK](https://developer.nvidia.com/nsight-aftermath). 4 | 5 | ## Samples 6 | 7 | * D3D12HelloNsightAftermath -- a very basic D3D12 application showing how to use the Nsight Aftermath API to capture GPU crash dumps. 8 | * GpuCrashDump -- an example GPU crash dump from the D3D12HelloNsightAftermath application. 9 | * VkHelloNsightAftermath -- a very basic Vulkan application showing how to use the Nsight Aftermath extension to capture GPU crash dumps. 10 | 11 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # ~~~ 2 | # Copyright (c) 2018 Valve Corporation 3 | # Copyright (c) 2018 LunarG, Inc. 4 | # Copyright (c) 2019-2025 NVIDIA Corporation 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # ~~~ 18 | 19 | # CMake project initialization --------------------------------------------------------------------------------------------------- 20 | # This section contains pre-project() initialization, and ends with the project() command. 21 | 22 | cmake_minimum_required(VERSION 3.17) 23 | 24 | project(VkHelloNsightAftermath) 25 | 26 | # find_package(), include() and global project settings -------------------------------------------------------------------------- 27 | 28 | 29 | # User-interface declarations ---------------------------------------------------------------------------------------------------- 30 | # This section contains variables that affect development GUIs (e.g. CMake GUI and IDEs), such as option(), folders, and variables 31 | # with the CACHE property. 32 | 33 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 34 | 35 | option(BUILD_VKHELLONSIGHTAFTERMATH "Build VkHelloNsightAftermath" ON) 36 | 37 | if(APPLE) 38 | message(FATAL_ERROR "Apple platform is not supported by Nsight Aftermath") 39 | endif() 40 | 41 | 42 | # # Enable IDE GUI folders 43 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 44 | 45 | option(USE_CCACHE "Use ccache" OFF) 46 | if(USE_CCACHE) 47 | find_program(CCACHE_FOUND ccache) 48 | if(CCACHE_FOUND) 49 | set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) 50 | endif() 51 | endif() 52 | 53 | # ~~~ 54 | # Find Vulkan Headers and Loader 55 | # Search order: 56 | # User-supplied CMAKE_PREFIX_PATH containing paths to the header and/or loader install dirs 57 | # CMake options VULKAN_HEADERS_INSTALL_DIR and/or VULKAN_LOADER_INSTALL_DIR 58 | # Env vars VULKAN_HEADERS_INSTALL_DIR and/or VULKAN_LOADER_INSTALL_DIR 59 | # If on MacOS 60 | # CMake option MOTLENVK_REPO_ROOT 61 | # Env vars MOLTENVK_REPO_ROOT 62 | # Fallback to FindVulkan operation using SDK install or system installed components. 63 | # ~~~ 64 | set(VULKAN_HEADERS_INSTALL_DIR "HEADERS-NOTFOUND" CACHE PATH "Absolute path to a Vulkan-Headers install directory") 65 | set(VULKAN_LOADER_INSTALL_DIR "LOADER-NOTFOUND" CACHE PATH "Absolute path to a Vulkan-Loader install directory") 66 | if(WIN32 AND "${VULKAN_LOADER_INSTALL_DIR}" STREQUAL "LOADER-NOTFOUND") 67 | if(CMAKE_CL_64) 68 | set(VULKAN_LOADER_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/x64") 69 | else() 70 | set(VULKAN_LOADER_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/x86") 71 | endif() 72 | endif() 73 | set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH};${VULKAN_HEADERS_INSTALL_DIR};${VULKAN_LOADER_INSTALL_DIR}; 74 | $ENV{VULKAN_HEADERS_INSTALL_DIR};$ENV{VULKAN_LOADER_INSTALL_DIR}) 75 | 76 | message(STATUS "Using find_package to locate Vulkan") 77 | find_package(Vulkan) 78 | find_package(VulkanHeaders) 79 | get_filename_component(Vulkan_LIBRARY_DIR ${Vulkan_LIBRARY} DIRECTORY) 80 | message(STATUS "Vulkan FOUND = ${Vulkan_FOUND}") 81 | message(STATUS "Vulkan Lib Dir = ${Vulkan_LIBRARY_DIR}") 82 | message(STATUS "Vulkan Lib = ${Vulkan_LIBRARY}") 83 | message(STATUS "Vulkan Headers Include = ${VulkanHeaders_INCLUDE_DIR}") 84 | message(STATUS "Vulkan Headers Registry = ${VulkanRegistry_DIR}") 85 | 86 | # ~~~ 87 | # Find Nsight Aftermath SDK Headers and Library 88 | # ~~~ 89 | message(STATUS "Using find_package to locate Nsight Aftermath SDK") 90 | find_package(NsightAftermath) 91 | get_filename_component(NsightAftermath_LIBRARY_DIR ${NsightAftermath_LIBRARY} DIRECTORY) 92 | message(STATUS "Nsight Aftermath FOUND = ${NsightAftermath_FOUND}") 93 | message(STATUS "Nsight Aftermath Lib Dir = ${NsightAftermath_LIBRARY_DIR}") 94 | message(STATUS "Nsight Aftermath Lib = ${NsightAftermath_LIBRARY}") 95 | message(STATUS "Nsight Aftermath Headers Include = ${NsightAftermath_INCLUDE_DIR}") 96 | 97 | include(GNUInstallDirs) 98 | 99 | if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") 100 | set(COMMON_COMPILE_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers") 101 | set(COMMON_COMPILE_FLAGS "${COMMON_COMPILE_FLAGS} -fno-strict-aliasing -fno-builtin-memcmp") 102 | 103 | # For GCC version 7.1 or greater, we need to disable the implicit fallthrough warning since there's no consistent way to satisfy 104 | # all compilers until they all accept the C++17 standard 105 | if(CMAKE_COMPILER_IS_GNUCC AND NOT (CMAKE_CXX_COMPILER_VERSION LESS 7.1)) 106 | set(COMMON_COMPILE_FLAGS "${COMMON_COMPILE_FLAGS} -Wimplicit-fallthrough=0") 107 | endif() 108 | 109 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMMON_COMPILE_FLAGS} -std=c++11 -fno-rtti") 110 | if(UNIX) 111 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") 112 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden") 113 | endif() 114 | endif() 115 | 116 | set(VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.. ${VulkanHeaders_INCLUDE_DIR}) 117 | 118 | if (NOT GLSLANG_INSTALL_DIR AND DEFINED ENV{GLSLANG_INSTALL_DIR}) 119 | set(GLSLANG_INSTALL_DIR $ENV{GLSLANG_INSTALL_DIR}) 120 | elseif(NOT GLSLANG_INSTALL_DIR AND Vulkan_FOUND) 121 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 122 | set(GLSLANG_INSTALL_DIR $ENV{GLSLANG_INSTALL_DIR}/Bin) 123 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 124 | set(GLSLANG_INSTALL_DIR $ENV{GLSLANG_INSTALL_DIR}/Bin32) 125 | endif() 126 | endif() 127 | 128 | if(GLSLANG_INSTALL_DIR) 129 | message(STATUS "Using GLSLANG_INSTALL_DIR to look for glslangValidator") 130 | find_program(GLSLANG_VALIDATOR NAMES glslangValidator HINTS "${GLSLANG_INSTALL_DIR}/bin" "$ENV{VULKAN_SDK}/bin" "$ENV{VULKAN_SDK}/Bin") 131 | find_program(SPIRV_REMAP NAMES spirv-remap HINTS "${GLSLANG_INSTALL_DIR}/bin" "$ENV{VULKAN_SDK}/bin" "$ENV{VULKAN_SDK}/Bin") 132 | endif() 133 | 134 | if(UNIX) # i.e. Linux 135 | include(FindPkgConfig) 136 | option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON) 137 | option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON) 138 | option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON) 139 | set(VKHELLONSIGHTAFTERMATH_WSI_SELECTION "XCB" CACHE STRING "Select WSI target for VkHelloNsightAftermath (XCB, XLIB, WAYLAND, DISPLAY)") 140 | 141 | if(BUILD_WSI_XCB_SUPPORT) 142 | find_package(XCB REQUIRED) 143 | endif() 144 | 145 | if(BUILD_WSI_XLIB_SUPPORT) 146 | find_package(X11 REQUIRED) 147 | endif() 148 | 149 | if(BUILD_WSI_WAYLAND_SUPPORT) 150 | find_package(Wayland REQUIRED) 151 | include_directories(${WAYLAND_CLIENT_INCLUDE_DIR}) 152 | endif() 153 | endif() 154 | 155 | if(WIN32) 156 | add_definitions(-DVK_USE_PLATFORM_WIN32_KHR -DWIN32_LEAN_AND_MEAN -DNOMINMAX) 157 | if(NOT MSVC_VERSION LESS 1900) 158 | # Enable control flow guard 159 | message(STATUS "Building VkHelloNsightAftermath with control flow guard") 160 | add_compile_options("$<$:/guard:cf>") 161 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf") 162 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf") 163 | endif() 164 | elseif(UNIX) # i.e. Linux 165 | if(NOT VKHELLONSIGHTAFTERMATH_WSI_SELECTION) 166 | set(VKHELLONSIGHTAFTERMATH_WSI_SELECTION "XCB") 167 | endif() 168 | 169 | if(VKHELLONSIGHTAFTERMATH_WSI_SELECTION STREQUAL "XCB") 170 | if(NOT BUILD_WSI_XCB_SUPPORT) 171 | message(FATAL_ERROR "Selected XCB for VkHelloNsightAftermath build but not building Xcb support") 172 | endif() 173 | set(VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS ${XCB_INCLUDE_DIRS} ${VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS}) 174 | link_libraries(${XCB_LIBRARIES}) 175 | add_definitions(-DVK_USE_PLATFORM_XCB_KHR) 176 | elseif(VKHELLONSIGHTAFTERMATH_WSI_SELECTION STREQUAL "XLIB") 177 | if(NOT BUILD_WSI_XLIB_SUPPORT) 178 | message(FATAL_ERROR "Selected XLIB for VkHelloNsightAftermath build but not building Xlib support") 179 | endif() 180 | set(VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS ${X11_INCLUDE_DIR} ${VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS}) 181 | link_libraries(${X11_LIBRARIES}) 182 | add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) 183 | elseif(VKHELLONSIGHTAFTERMATH_WSI_SELECTION STREQUAL "WAYLAND") 184 | if(NOT BUILD_WSI_WAYLAND_SUPPORT) 185 | message(FATAL_ERROR "Selected Wayland for VkHelloNsightAftermath build but not building Wayland support") 186 | endif() 187 | set(VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS ${WAYLAND_CLIENT_INCLUDE_DIR} ${VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS}) 188 | link_libraries(${WAYLAND_CLIENT_LIBRARIES}) 189 | add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR) 190 | elseif(VKHELLONSIGHTAFTERMATH_WSI_SELECTION STREQUAL "DISPLAY") 191 | add_definitions(-DVK_USE_PLATFORM_DISPLAY_KHR) 192 | else() 193 | message(FATAL_ERROR "Unrecognized value for VKHELLONSIGHTAFTERMATH_WSI_SELECTION: ${VKHELLONSIGHTAFTERMATH_WSI_SELECTION}") 194 | endif() 195 | 196 | link_libraries(${API_LOWERCASE} m) 197 | else() 198 | message(FATAL_ERROR "Unsupported Platform!") 199 | endif() 200 | 201 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 202 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 203 | 204 | if(WIN32) 205 | # Use static MSVCRT libraries 206 | foreach(configuration 207 | in 208 | CMAKE_C_FLAGS_DEBUG 209 | CMAKE_C_FLAGS_MINSIZEREL 210 | CMAKE_C_FLAGS_RELEASE 211 | CMAKE_C_FLAGS_RELWITHDEBINFO 212 | CMAKE_CXX_FLAGS_DEBUG 213 | CMAKE_CXX_FLAGS_MINSIZEREL 214 | CMAKE_CXX_FLAGS_RELEASE 215 | CMAKE_CXX_FLAGS_RELWITHDEBINFO) 216 | if(${configuration} MATCHES "/MD") 217 | string(REGEX 218 | REPLACE "/MD" 219 | "/MT" 220 | ${configuration} 221 | "${${configuration}}") 222 | endif() 223 | endforeach() 224 | 225 | endif() 226 | 227 | add_custom_command(COMMENT "Compiling cube vertex shader" 228 | OUTPUT cube.vert.spirv 229 | COMMAND ${GLSLANG_VALIDATOR} -V -g -o $/cube.vert.full.spirv 230 | ${PROJECT_SOURCE_DIR}/cube.vert 231 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.vert.full.spirv ${CMAKE_BINARY_DIR}/cube.vert.full.spirv 232 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.vert.full.spirv $/cube.vert.spirv 233 | COMMAND ${CMAKE_COMMAND} -E chdir $ ${SPIRV_REMAP} --map all --strip-all --input cube.vert.spirv --output ./ 234 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.vert.spirv ${CMAKE_BINARY_DIR}/cube.vert.spirv 235 | MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/cube.vert 236 | DEPENDS ${PROJECT_SOURCE_DIR}/cube.vert ${GLSLANG_VALIDATOR} ${SPIRV_REMAP}) 237 | add_custom_command(COMMENT "Compiling cube fragment shader" 238 | OUTPUT cube.frag.spirv 239 | COMMAND ${GLSLANG_VALIDATOR} -V -g -o $/cube.frag.full.spirv 240 | ${PROJECT_SOURCE_DIR}/cube.frag 241 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.frag.full.spirv ${CMAKE_BINARY_DIR}/cube.frag.full.spirv 242 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.frag.full.spirv $/cube.frag.spirv 243 | COMMAND ${CMAKE_COMMAND} -E chdir $ ${SPIRV_REMAP} --map all --strip-all --input cube.frag.spirv --output ./ 244 | COMMAND ${CMAKE_COMMAND} -E copy $/cube.frag.spirv ${CMAKE_BINARY_DIR}/cube.frag.spirv 245 | MAIN_DEPENDENCY ${PROJECT_SOURCE_DIR}/cube.frag 246 | DEPENDS ${PROJECT_SOURCE_DIR}/cube.frag ${GLSLANG_VALIDATOR}) 247 | 248 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 249 | 250 | if(WIN32) 251 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES") 252 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES") 253 | endif() 254 | 255 | include_directories(${VKHELLONSIGHTAFTERMATH_INCLUDE_DIRS}) 256 | 257 | # ---------------------------------------------------------------------------- 258 | # VkHelloNsightAftermath 259 | 260 | if(NOT WIN32) 261 | if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL ${CMAKE_HOST_SYSTEM_PROCESSOR}) 262 | add_executable(VkHelloNsightAftermath 263 | VkHelloNsightAftermath.cpp 264 | NsightAftermathGpuCrashTracker.cpp 265 | NsightAftermathShaderDatabase.cpp 266 | cube.vert 267 | cube.frag 268 | cube.vert.spirv 269 | cube.frag.spirv) 270 | target_link_libraries(VkHelloNsightAftermath PRIVATE Vulkan::Vulkan NsightAftermath::NsightAftermath dl) 271 | target_compile_options(VkHelloNsightAftermath PRIVATE -DVULKAN_HPP_DISABLE_IMPLICIT_RESULT_VALUE_CAST) 272 | endif() 273 | else() 274 | if(CMAKE_CL_64) 275 | set(LIB_DIR "Win64") 276 | else() 277 | set(LIB_DIR "Win32") 278 | endif() 279 | 280 | add_executable(VkHelloNsightAftermath 281 | WIN32 282 | VkHelloNsightAftermath.cpp 283 | NsightAftermathGpuCrashTracker.cpp 284 | NsightAftermathShaderDatabase.cpp 285 | cube.vert 286 | cube.frag 287 | cube.vert.spirv 288 | cube.frag.spirv) 289 | target_link_libraries(VkHelloNsightAftermath PRIVATE Vulkan::Vulkan NsightAftermath::NsightAftermath) 290 | target_compile_options(VkHelloNsightAftermath PRIVATE -DVULKAN_HPP_DISABLE_IMPLICIT_RESULT_VALUE_CAST) 291 | 292 | # Add post-build step to copy Nsight Aftermath DLL to the installation directory 293 | add_custom_command(TARGET VkHelloNsightAftermath POST_BUILD 294 | COMMAND ${CMAKE_COMMAND} -E copy_if_different 295 | "${NsightAftermath_DLL}" 296 | $ 297 | COMMENT "Copying Nsight Aftermath DLL to output directory") 298 | 299 | # Also install the DLL to the installation directory 300 | install(FILES "${NsightAftermath_DLL}" DESTINATION ${CMAKE_INSTALL_BINDIR}) 301 | endif() 302 | 303 | install(TARGETS VkHelloNsightAftermath RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 304 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright (c) 2015-2019, The Khronos Group Inc 191 | Copyright (c) 2019, NVIDIA CORPORATION. 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/NsightAftermathGpuCrashTracker.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "NsightAftermathGpuCrashTracker.h" 31 | 32 | //********************************************************* 33 | // GpuCrashTracker implementation 34 | //********************************************************* 35 | 36 | GpuCrashTracker::GpuCrashTracker(const MarkerMap& markerMap) 37 | : m_initialized(false) 38 | , m_mutex() 39 | , m_shaderDebugInfo() 40 | , m_shaderDatabase() 41 | , m_markerMap(markerMap) 42 | { 43 | } 44 | 45 | GpuCrashTracker::~GpuCrashTracker() 46 | { 47 | // If initialized, disable GPU crash dumps 48 | if (m_initialized) 49 | { 50 | GFSDK_Aftermath_DisableGpuCrashDumps(); 51 | } 52 | } 53 | 54 | // Initialize the GPU Crash Dump Tracker 55 | void GpuCrashTracker::Initialize(bool applicationUsesStrippedShaders) 56 | { 57 | // Initialize the shader database with the application's shader configuration 58 | m_shaderDatabase.Initialize(applicationUsesStrippedShaders); 59 | 60 | // Enable GPU crash dumps and set up the callbacks for crash dump notifications, 61 | // shader debug information notifications, and providing additional crash 62 | // dump description data.Only the crash dump callback is mandatory. The other two 63 | // callbacks are optional and can be omitted, by passing nullptr, if the corresponding 64 | // functionality is not used. 65 | // The DeferDebugInfoCallbacks flag enables caching of shader debug information data 66 | // in memory. If the flag is set, ShaderDebugInfoCallback will be called only 67 | // in the event of a crash, right before GpuCrashDumpCallback. If the flag is not set, 68 | // ShaderDebugInfoCallback will be called for every shader that is compiled. 69 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_EnableGpuCrashDumps( 70 | GFSDK_Aftermath_Version_API, 71 | GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan, 72 | GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks, // Let the Nsight Aftermath library cache shader debug information. 73 | GpuCrashDumpCallback, // Register callback for GPU crash dumps. 74 | ShaderDebugInfoCallback, // Register callback for shader debug information. 75 | CrashDumpDescriptionCallback, // Register callback for GPU crash dump description. 76 | ResolveMarkerCallback, // Register callback for resolving application-managed markers. 77 | this)); // Set the GpuCrashTracker object as user data for the above callbacks. 78 | 79 | m_initialized = true; 80 | } 81 | 82 | // Handler for GPU crash dump callbacks from Nsight Aftermath 83 | void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) 84 | { 85 | // Make sure only one thread at a time... 86 | std::lock_guard lock(m_mutex); 87 | 88 | // Write to file for later in-depth analysis with Nsight Graphics. 89 | WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); 90 | } 91 | 92 | // Handler for shader debug information callbacks 93 | void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) 94 | { 95 | // Make sure only one thread at a time... 96 | std::lock_guard lock(m_mutex); 97 | 98 | // Get shader debug information identifier 99 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; 100 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugInfoIdentifier( 101 | GFSDK_Aftermath_Version_API, 102 | pShaderDebugInfo, 103 | shaderDebugInfoSize, 104 | &identifier)); 105 | 106 | // Store information for decoding of GPU crash dumps with shader address mapping 107 | // from within the application. 108 | std::vector data((uint8_t*)pShaderDebugInfo, (uint8_t*)pShaderDebugInfo + shaderDebugInfoSize); 109 | m_shaderDebugInfo[identifier].swap(data); 110 | 111 | // Write to file for later in-depth analysis of crash dumps with Nsight Graphics 112 | WriteShaderDebugInformationToFile(identifier, pShaderDebugInfo, shaderDebugInfoSize); 113 | } 114 | 115 | // Handler for GPU crash dump description callbacks 116 | void GpuCrashTracker::OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription) 117 | { 118 | // Add some basic description about the crash. This is called after the GPU crash happens, but before 119 | // the actual GPU crash dump callback. The provided data is included in the crash dump and can be 120 | // retrieved using GFSDK_Aftermath_GpuCrashDump_GetDescription(). 121 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "VkHelloNsightAftermath"); 122 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion, "v1.0"); 123 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined, "This is a GPU crash dump example."); 124 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 1, "Engine State: Rendering."); 125 | addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 2, "More user-defined information..."); 126 | } 127 | 128 | // Handler for app-managed marker resolve callback 129 | void GpuCrashTracker::OnResolveMarker(const void* pMarkerData, const uint32_t markerDataSize, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize) 130 | { 131 | // Important: the pointer passed back via ppResolvedMarkerData must remain valid after this function returns 132 | // using references for all of the m_markerMap accesses ensures that the pointers refer to the persistent data 133 | for (auto& map : m_markerMap) 134 | { 135 | const auto& foundMarker = map.find((uint64_t)pMarkerData); 136 | if (foundMarker != map.end()) 137 | { 138 | const std::string& foundMarkerData = foundMarker->second; 139 | // std::string::data() will return a valid pointer until the string is next modified 140 | // we don't modify the string after calling data() here, so the pointer should remain valid 141 | *ppResolvedMarkerData = (void*)foundMarkerData.data(); 142 | *pResolvedMarkerDataSize = (uint32_t)foundMarkerData.length(); 143 | return; 144 | } 145 | } 146 | } 147 | 148 | // Helper for writing a GPU crash dump to a file 149 | void GpuCrashTracker::WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) 150 | { 151 | // Create a GPU crash dump decoder object for the GPU crash dump. 152 | GFSDK_Aftermath_GpuCrashDump_Decoder decoder = {}; 153 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_CreateDecoder( 154 | GFSDK_Aftermath_Version_API, 155 | pGpuCrashDump, 156 | gpuCrashDumpSize, 157 | &decoder)); 158 | 159 | // Use the decoder object to read basic information, like application 160 | // name, PID, etc. from the GPU crash dump. 161 | GFSDK_Aftermath_GpuCrashDump_BaseInfo baseInfo = {}; 162 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetBaseInfo(decoder, &baseInfo)); 163 | 164 | // Use the decoder object to query the application name that was set 165 | // in the GPU crash dump description. 166 | uint32_t applicationNameLength = 0; 167 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize( 168 | decoder, 169 | GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, 170 | &applicationNameLength)); 171 | 172 | std::vector applicationName(applicationNameLength, '\0'); 173 | 174 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescription( 175 | decoder, 176 | GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, 177 | uint32_t(applicationName.size()), 178 | applicationName.data())); 179 | 180 | // Create a unique file name for writing the crash dump data to a file. 181 | // Note: due to an Nsight Aftermath bug (will be fixed in an upcoming 182 | // driver release) we may see redundant crash dumps. As a workaround, 183 | // attach a unique count to each generated file name. 184 | static int count = 0; 185 | const std::string baseFileName = 186 | std::string(applicationName.data()) 187 | + "-" 188 | + std::to_string(baseInfo.pid) 189 | + "-" 190 | + std::to_string(++count); 191 | 192 | // Write the crash dump data to a file using the .nv-gpudmp extension 193 | // registered with Nsight Graphics. 194 | const std::string crashDumpFileName = baseFileName + ".nv-gpudmp"; 195 | std::ofstream dumpFile(crashDumpFileName, std::ios::out | std::ios::binary); 196 | if (dumpFile) 197 | { 198 | dumpFile.write((const char*)pGpuCrashDump, gpuCrashDumpSize); 199 | dumpFile.close(); 200 | } 201 | 202 | // Decode the crash dump to a JSON string. 203 | // Step 1: Generate the JSON and get the size. 204 | uint32_t jsonSize = 0; 205 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GenerateJSON( 206 | decoder, 207 | GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO, 208 | GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE, 209 | ShaderDebugInfoLookupCallback, 210 | ShaderLookupCallback, 211 | ShaderSourceDebugInfoLookupCallback, 212 | this, 213 | &jsonSize)); 214 | // Step 2: Allocate a buffer and fetch the generated JSON. 215 | std::vector json(jsonSize); 216 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetJSON( 217 | decoder, 218 | uint32_t(json.size()), 219 | json.data())); 220 | 221 | // Write the crash dump data as JSON to a file. 222 | const std::string jsonFileName = crashDumpFileName + ".json"; 223 | std::ofstream jsonFile(jsonFileName, std::ios::out | std::ios::binary); 224 | if (jsonFile) 225 | { 226 | // Write the JSON to the file (excluding string termination) 227 | jsonFile.write(json.data(), json.size() - 1); 228 | jsonFile.close(); 229 | } 230 | 231 | // Destroy the GPU crash dump decoder object. 232 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder)); 233 | } 234 | 235 | // Helper for writing shader debug information to a file 236 | void GpuCrashTracker::WriteShaderDebugInformationToFile( 237 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, 238 | const void* pShaderDebugInfo, 239 | const uint32_t shaderDebugInfoSize) 240 | { 241 | // Create a unique file name. 242 | const std::string filePath = "shader-" + std::to_string(identifier) + ".nvdbg"; 243 | 244 | std::ofstream f(filePath, std::ios::out | std::ios::binary); 245 | if (f) 246 | { 247 | f.write((const char*)pShaderDebugInfo, shaderDebugInfoSize); 248 | } 249 | } 250 | 251 | // Handler for shader debug information lookup callbacks. 252 | // This is used by the JSON decoder for mapping shader instruction 253 | // addresses to SPIR-V IL lines or GLSL source lines. 254 | void GpuCrashTracker::OnShaderDebugInfoLookup( 255 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, 256 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const 257 | { 258 | // Search the list of shader debug information blobs received earlier. 259 | auto i_debugInfo = m_shaderDebugInfo.find(identifier); 260 | if (i_debugInfo == m_shaderDebugInfo.end()) 261 | { 262 | // Early exit, nothing found. No need to call setShaderDebugInfo. 263 | return; 264 | } 265 | 266 | // Let the GPU crash dump decoder know about the shader debug information 267 | // that was found. 268 | setShaderDebugInfo(i_debugInfo->second.data(), uint32_t(i_debugInfo->second.size())); 269 | } 270 | 271 | // Handler for shader lookup callbacks. 272 | // This is used by the JSON decoder for mapping shader instruction 273 | // addresses to SPIR-V IL lines or GLSL source lines. 274 | // NOTE: If the application loads stripped shader binaries (ie; --strip-all in spirv-remap), 275 | // Aftermath will require access to both the stripped and the not stripped 276 | // shader binaries. 277 | void GpuCrashTracker::OnShaderLookup( 278 | const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, 279 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const 280 | { 281 | // Find shader binary data for the shader hash in the shader database. 282 | std::vector shaderBinary; 283 | if (!m_shaderDatabase.FindShaderBinary(shaderHash, shaderBinary)) 284 | { 285 | // Early exit, nothing found. No need to call setShaderBinary. 286 | return; 287 | } 288 | 289 | // Let the GPU crash dump decoder know about the shader data 290 | // that was found. 291 | setShaderBinary(shaderBinary.data(), uint32_t(shaderBinary.size())); 292 | } 293 | 294 | // Handler for shader source debug info lookup callbacks. 295 | // This is used by the JSON decoder for mapping shader instruction addresses to 296 | // GLSL source lines, if the shaders used by the application were compiled with 297 | // separate debug info data files. 298 | void GpuCrashTracker::OnShaderSourceDebugInfoLookup( 299 | const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, 300 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const 301 | { 302 | // Find source debug info for the shader DebugName in the shader database. 303 | std::vector shaderBinary; 304 | if (!m_shaderDatabase.FindShaderBinaryWithDebugData(shaderDebugName, shaderBinary)) 305 | { 306 | // Early exit, nothing found. No need to call setShaderBinary. 307 | return; 308 | } 309 | 310 | // Let the GPU crash dump decoder know about the shader debug data that was 311 | // found. 312 | setShaderBinary(shaderBinary.data(), uint32_t(shaderBinary.size())); 313 | } 314 | 315 | // Static callback wrapper for OnCrashDump 316 | void GpuCrashTracker::GpuCrashDumpCallback( 317 | const void* pGpuCrashDump, 318 | const uint32_t gpuCrashDumpSize, 319 | void* pUserData) 320 | { 321 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 322 | pGpuCrashTracker->OnCrashDump(pGpuCrashDump, gpuCrashDumpSize); 323 | } 324 | 325 | // Static callback wrapper for OnShaderDebugInfo 326 | void GpuCrashTracker::ShaderDebugInfoCallback( 327 | const void* pShaderDebugInfo, 328 | const uint32_t shaderDebugInfoSize, 329 | void* pUserData) 330 | { 331 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 332 | pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize); 333 | } 334 | 335 | // Static callback wrapper for OnDescription 336 | void GpuCrashTracker::CrashDumpDescriptionCallback( 337 | PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, 338 | void* pUserData) 339 | { 340 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 341 | pGpuCrashTracker->OnDescription(addDescription); 342 | } 343 | 344 | // Static callback wrapper for OnResolveMarker 345 | void GpuCrashTracker::ResolveMarkerCallback( 346 | const void* pMarkerData, 347 | const uint32_t markerDataSize, 348 | void* pUserData, 349 | void** ppResolvedMarkerData, 350 | uint32_t* pResolvedMarkerDataSize) 351 | { 352 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 353 | pGpuCrashTracker->OnResolveMarker(pMarkerData, markerDataSize, ppResolvedMarkerData, pResolvedMarkerDataSize); 354 | } 355 | 356 | // Static callback wrapper for OnShaderDebugInfoLookup 357 | void GpuCrashTracker::ShaderDebugInfoLookupCallback( 358 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, 359 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, 360 | void* pUserData) 361 | { 362 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 363 | pGpuCrashTracker->OnShaderDebugInfoLookup(*pIdentifier, setShaderDebugInfo); 364 | } 365 | 366 | // Static callback wrapper for OnShaderLookup 367 | void GpuCrashTracker::ShaderLookupCallback( 368 | const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, 369 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 370 | void* pUserData) 371 | { 372 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 373 | pGpuCrashTracker->OnShaderLookup(*pShaderHash, setShaderBinary); 374 | } 375 | 376 | // Static callback wrapper for OnShaderSourceDebugInfoLookup 377 | void GpuCrashTracker::ShaderSourceDebugInfoLookupCallback( 378 | const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, 379 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 380 | void* pUserData) 381 | { 382 | GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); 383 | pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary); 384 | } 385 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/NsightAftermathGpuCrashTracker.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | 30 | #include "NsightAftermathHelpers.h" 31 | #include "NsightAftermathShaderDatabase.h" 32 | 33 | //********************************************************* 34 | // Implements GPU crash dump tracking using the Nsight 35 | // Aftermath API. 36 | // 37 | class GpuCrashTracker 38 | { 39 | public: 40 | // keep four frames worth of marker history 41 | const static unsigned int c_markerFrameHistory = 4; 42 | typedef std::array, c_markerFrameHistory> MarkerMap; 43 | 44 | GpuCrashTracker(const MarkerMap& markerMap); 45 | ~GpuCrashTracker(); 46 | 47 | // Initialize the GPU crash dump tracker. 48 | void Initialize(bool applicationUsesStrippedShaders); 49 | 50 | private: 51 | 52 | //********************************************************* 53 | // Callback handlers for GPU crash dumps and related data. 54 | // 55 | 56 | // Handler for GPU crash dump callbacks. 57 | void OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); 58 | 59 | // Handler for shader debug information callbacks. 60 | void OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize); 61 | 62 | // Handler for GPU crash dump description callbacks. 63 | void OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription); 64 | 65 | // Handler for app-managed marker resolve callback 66 | void OnResolveMarker(const void* pMarkerData, const uint32_t markerDataSize, void** ppResolvedMarkerData, uint32_t* pResolvedMarkerDataSize); 67 | 68 | //********************************************************* 69 | // Helpers for writing a GPU crash dump and debug information 70 | // data to files. 71 | // 72 | 73 | // Helper for writing a GPU crash dump to a file. 74 | void WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); 75 | 76 | // Helper for writing shader debug information to a file 77 | void WriteShaderDebugInformationToFile( 78 | GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, 79 | const void* pShaderDebugInfo, 80 | const uint32_t shaderDebugInfoSize); 81 | 82 | //********************************************************* 83 | // Helpers for decoding GPU crash dump to JSON. 84 | // 85 | 86 | // Handler for shader debug info lookup callbacks. 87 | void OnShaderDebugInfoLookup( 88 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, 89 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const; 90 | 91 | // Handler for shader lookup callbacks. 92 | void OnShaderLookup( 93 | const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, 94 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const; 95 | 96 | // Handler for shader source debug info lookup callbacks. 97 | void OnShaderSourceDebugInfoLookup( 98 | const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, 99 | PFN_GFSDK_Aftermath_SetData setShaderBinary) const; 100 | 101 | //********************************************************* 102 | // Static callback wrappers. 103 | // 104 | 105 | // GPU crash dump callback. 106 | static void GpuCrashDumpCallback( 107 | const void* pGpuCrashDump, 108 | const uint32_t gpuCrashDumpSize, 109 | void* pUserData); 110 | 111 | // Shader debug information callback. 112 | static void ShaderDebugInfoCallback( 113 | const void* pShaderDebugInfo, 114 | const uint32_t shaderDebugInfoSize, 115 | void* pUserData); 116 | 117 | // GPU crash dump description callback. 118 | static void CrashDumpDescriptionCallback( 119 | PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, 120 | void* pUserData); 121 | 122 | // App-managed marker resolve callback 123 | static void ResolveMarkerCallback( 124 | const void* pMarkerData, 125 | const uint32_t markerDataSize, 126 | void* pUserData, 127 | void** ppResolvedMarkerData, 128 | uint32_t* pResolvedMarkerDataSize); 129 | 130 | // Shader debug information lookup callback. 131 | static void ShaderDebugInfoLookupCallback( 132 | const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, 133 | PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, 134 | void* pUserData); 135 | 136 | // Shader lookup callback. 137 | static void ShaderLookupCallback( 138 | const GFSDK_Aftermath_ShaderBinaryHash* pShaderHash, 139 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 140 | void* pUserData); 141 | 142 | // Shader source debug info lookup callback. 143 | static void ShaderSourceDebugInfoLookupCallback( 144 | const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, 145 | PFN_GFSDK_Aftermath_SetData setShaderBinary, 146 | void* pUserData); 147 | 148 | //********************************************************* 149 | // GPU crash tracker state. 150 | // 151 | 152 | // Is the GPU crash dump tracker initialized? 153 | bool m_initialized; 154 | 155 | // For thread-safe access of GPU crash tracker state. 156 | mutable std::mutex m_mutex; 157 | 158 | // List of Shader Debug Information by ShaderDebugInfoIdentifier. 159 | std::map> m_shaderDebugInfo; 160 | 161 | // The mock shader database. 162 | ShaderDatabase m_shaderDatabase; 163 | 164 | // App-managed marker tracking 165 | const MarkerMap& m_markerMap; 166 | }; 167 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/NsightAftermathHelpers.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include "GFSDK_Aftermath.h" 33 | #include "GFSDK_Aftermath_GpuCrashDump.h" 34 | #include "GFSDK_Aftermath_GpuCrashDumpDecoding.h" 35 | 36 | //********************************************************* 37 | // Some std::to_string overloads for some Nsight Aftermath 38 | // API types. 39 | // 40 | 41 | namespace std 42 | { 43 | template 44 | inline std::string to_hex_string(T n) 45 | { 46 | std::stringstream stream; 47 | stream << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex << n; 48 | return stream.str(); 49 | } 50 | 51 | inline std::string to_string(GFSDK_Aftermath_Result result) 52 | { 53 | return std::string("0x") + to_hex_string(static_cast(result)); 54 | } 55 | 56 | inline std::string to_string(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier) 57 | { 58 | return to_hex_string(identifier.id[0]) + "-" + to_hex_string(identifier.id[1]); 59 | } 60 | 61 | inline std::string to_string(const GFSDK_Aftermath_ShaderBinaryHash& hash) 62 | { 63 | return to_hex_string(hash.hash); 64 | } 65 | } // namespace std 66 | 67 | //********************************************************* 68 | // Helper for comparing shader hashes and debug info identifier. 69 | // 70 | 71 | // Helper for comparing GFSDK_Aftermath_ShaderDebugInfoIdentifier. 72 | inline bool operator<(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& lhs, const GFSDK_Aftermath_ShaderDebugInfoIdentifier& rhs) 73 | { 74 | if (lhs.id[0] == rhs.id[0]) 75 | { 76 | return lhs.id[1] < rhs.id[1]; 77 | } 78 | return lhs.id[0] < rhs.id[0]; 79 | } 80 | 81 | // Helper for comparing GFSDK_Aftermath_ShaderBinaryHash. 82 | inline bool operator<(const GFSDK_Aftermath_ShaderBinaryHash& lhs, const GFSDK_Aftermath_ShaderBinaryHash& rhs) 83 | { 84 | return lhs.hash < rhs.hash; 85 | } 86 | 87 | // Helper for comparing GFSDK_Aftermath_ShaderDebugName. 88 | inline bool operator<(const GFSDK_Aftermath_ShaderDebugName& lhs, const GFSDK_Aftermath_ShaderDebugName& rhs) 89 | { 90 | return strncmp(lhs.name, rhs.name, sizeof(lhs.name)) < 0; 91 | } 92 | 93 | //********************************************************* 94 | // Helper for checking Nsight Aftermath failures. 95 | // 96 | 97 | inline std::string AftermathErrorMessage(GFSDK_Aftermath_Result result) 98 | { 99 | switch (result) 100 | { 101 | case GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported: 102 | return "Unsupported driver version - requires an NVIDIA R495 display driver or newer."; 103 | default: 104 | return "Aftermath Error 0x" + std::to_hex_string(result); 105 | } 106 | } 107 | 108 | // Helper macro for checking Nsight Aftermath results and throwing exception 109 | // in case of a failure. 110 | #ifdef _WIN32 111 | #define AFTERMATH_CHECK_ERROR(FC) \ 112 | [&]() { \ 113 | GFSDK_Aftermath_Result _result = FC; \ 114 | if (!GFSDK_Aftermath_SUCCEED(_result)) \ 115 | { \ 116 | MessageBoxA(0, AftermathErrorMessage(_result).c_str(), "Aftermath Error", MB_OK); \ 117 | exit(1); \ 118 | } \ 119 | }() 120 | #else 121 | #define AFTERMATH_CHECK_ERROR(FC) \ 122 | [&]() { \ 123 | GFSDK_Aftermath_Result _result = FC; \ 124 | if (!GFSDK_Aftermath_SUCCEED(_result)) \ 125 | { \ 126 | printf("%s\n", AftermathErrorMessage(_result).c_str()); \ 127 | fflush(stdout); \ 128 | exit(1); \ 129 | } \ 130 | }() 131 | #endif 132 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/NsightAftermathShaderDatabase.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #include 26 | #include 27 | 28 | #include "NsightAftermathShaderDatabase.h" 29 | 30 | //********************************************************* 31 | // ShaderDatabase implementation 32 | //********************************************************* 33 | 34 | ShaderDatabase::ShaderDatabase() 35 | : m_shaderBinaries() 36 | , m_shaderBinariesWithDebugInfo() 37 | { 38 | } 39 | 40 | ShaderDatabase::~ShaderDatabase() 41 | { 42 | } 43 | 44 | // Initialize the shader database with application shader configuration 45 | void ShaderDatabase::Initialize(bool applicationUsesStrippedShaders) 46 | { 47 | // Clear any existing data 48 | m_shaderBinaries.clear(); 49 | m_shaderBinariesWithDebugInfo.clear(); 50 | 51 | if (applicationUsesStrippedShaders) 52 | { 53 | // If the application passes shaders that were stripped of debug information 54 | // to the Vulkan API, both the stripped and the not stripped shader binaries need 55 | // to be registered here to allow them to be correlated when decoding a GPU 56 | // crash dump. 57 | 58 | // Add the shader binaries to the database 59 | AddShaderBinary("cube.vert.spirv"); 60 | AddShaderBinary("cube.frag.spirv"); 61 | 62 | // Add the not stripped shader binaries and the names of the corresponding 63 | // stripped shader binaries to the database. 64 | AddShaderBinaryWithDebugInfo("cube.vert.spirv", "cube.vert.full.spirv"); 65 | AddShaderBinaryWithDebugInfo("cube.frag.spirv", "cube.frag.full.spirv"); 66 | } 67 | else 68 | { 69 | // If the application passes shaders with debug information to the Vulkan API, 70 | // only those shader binaries need to be registered with the database to allow 71 | // them to be correlated when decoding a GPU crash dump. 72 | 73 | AddShaderBinary("cube.vert.full.spirv"); 74 | AddShaderBinary("cube.frag.full.spirv"); 75 | } 76 | } 77 | 78 | bool ShaderDatabase::ReadFile(const char* filename, std::vector& data) 79 | { 80 | std::ifstream fs(filename, std::ios::in | std::ios::binary); 81 | if (!fs) 82 | { 83 | return false; 84 | } 85 | 86 | fs.seekg(0, std::ios::end); 87 | data.resize(fs.tellg()); 88 | fs.seekg(0, std::ios::beg); 89 | fs.read(reinterpret_cast(data.data()), data.size()); 90 | fs.close(); 91 | 92 | return true; 93 | } 94 | 95 | void ShaderDatabase::AddShaderBinary(const char* shaderFilePath) 96 | { 97 | // Read the shader binary code from the file 98 | std::vector data; 99 | if (!ReadFile(shaderFilePath, data)) 100 | { 101 | return; 102 | } 103 | 104 | // Create shader hash for the shader 105 | const GFSDK_Aftermath_SpirvCode shader{ data.data(), uint32_t(data.size()) }; 106 | GFSDK_Aftermath_ShaderBinaryHash shaderHash; 107 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderHashSpirv( 108 | GFSDK_Aftermath_Version_API, 109 | &shader, 110 | &shaderHash)); 111 | 112 | // Store the data for shader mapping when decoding GPU crash dumps. 113 | // cf. FindShaderBinary() 114 | m_shaderBinaries[shaderHash].swap(data); 115 | } 116 | 117 | void ShaderDatabase::AddShaderBinaryWithDebugInfo(const char* strippedShaderFilePath, const char* shaderFilePath) 118 | { 119 | // Read the shader debug data from the file 120 | std::vector data; 121 | if (!ReadFile(shaderFilePath, data)) 122 | { 123 | return; 124 | } 125 | std::vector strippedData; 126 | if (!ReadFile(strippedShaderFilePath, strippedData)) 127 | { 128 | return; 129 | } 130 | 131 | // Generate shader debug name. 132 | GFSDK_Aftermath_ShaderDebugName debugName; 133 | const GFSDK_Aftermath_SpirvCode shader{ data.data(), uint32_t(data.size()) }; 134 | const GFSDK_Aftermath_SpirvCode strippedShader{ strippedData.data(), uint32_t(strippedData.size()) }; 135 | AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugNameSpirv( 136 | GFSDK_Aftermath_Version_API, 137 | &shader, 138 | &strippedShader, 139 | &debugName)); 140 | 141 | // Store the data for shader instruction address mapping when decoding GPU crash dumps. 142 | // cf. FindShaderBinaryWithDebugData() 143 | m_shaderBinariesWithDebugInfo[debugName].swap(data); 144 | } 145 | 146 | // Find a shader binary by shader hash. 147 | bool ShaderDatabase::FindShaderBinary(const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, std::vector& shader) const 148 | { 149 | // Find shader binary data for the shader hash 150 | auto i_shader = m_shaderBinaries.find(shaderHash); 151 | if (i_shader == m_shaderBinaries.end()) 152 | { 153 | // Nothing found. 154 | return false; 155 | } 156 | 157 | shader = i_shader->second; 158 | return true; 159 | } 160 | 161 | // Find a shader binary with debug information by shader debug name. 162 | bool ShaderDatabase::FindShaderBinaryWithDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& shader) const 163 | { 164 | // Find shader binary for the shader debug name. 165 | auto i_shader = m_shaderBinariesWithDebugInfo.find(shaderDebugName); 166 | if (i_shader == m_shaderBinariesWithDebugInfo.end()) 167 | { 168 | // Nothing found. 169 | return false; 170 | } 171 | 172 | shader = i_shader->second; 173 | return true; 174 | } 175 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/NsightAftermathShaderDatabase.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a 6 | // copy of this software and associated documentation files (the "Software"), 7 | // to deal in the Software without restriction, including without limitation 8 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | // and/or sell copies of the Software, and to permit persons to whom the 10 | // Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | // DEALINGS IN THE SOFTWARE. 22 | // 23 | //********************************************************* 24 | 25 | #pragma once 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "NsightAftermathHelpers.h" 32 | 33 | //********************************************************* 34 | // Implements a very simple shader database to help demonstrate 35 | // how to use the Nsight Aftermath GPU crash dump decoder API. 36 | // 37 | // In a real world scenario this would be part of an offline 38 | // analysis tool. This is for demonstration purposes only! 39 | // 40 | class ShaderDatabase 41 | { 42 | public: 43 | ShaderDatabase(); 44 | ~ShaderDatabase(); 45 | 46 | // Initialize the shader database 47 | void Initialize(bool applicationUsesStrippedShaders); 48 | 49 | // Find a shader bytecode binary by shader hash. 50 | bool FindShaderBinary(const GFSDK_Aftermath_ShaderBinaryHash& shaderHash, std::vector& shader) const; 51 | 52 | // Find a source shader debug info by shader debug name generated by the DXC compiler. 53 | bool FindShaderBinaryWithDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& shader) const; 54 | 55 | private: 56 | 57 | void AddShaderBinary(const char* shaderFilePath); 58 | void AddShaderBinaryWithDebugInfo(const char* strippedShaderFilePath, const char* shaderFilePath); 59 | 60 | static bool ReadFile(const char* filename, std::vector& data); 61 | 62 | // List of shader binaries by ShaderBinaryHash. 63 | std::map> m_shaderBinaries; 64 | 65 | // List of available shader binaries with source debug information by ShaderDebugName. 66 | std::map> m_shaderBinariesWithDebugInfo; 67 | }; 68 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/README.md: -------------------------------------------------------------------------------- 1 | # Example for Nsight Aftermath GPU Crash Dump User Application Integration 2 | 3 | This sample source code shows how to integrate Nsight Aftermath GPU crash dump 4 | collection and decoding into a Vulkan application. 5 | 6 | ## Requirements 7 | 8 | On Windows 9 | 10 | * [Windows SDK 10.0.22621.755 (October 2022 Update) or newer](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk) 11 | * [CMake 3.17 or newer](https://cmake.org/download) 12 | * [Vulkan-SDK (1.2.135 or newer)](https://vulkan.lunarg.com/sdk/home) 13 | * [Nsight Aftermath SDK 2023.2 or newer](https://developer.nvidia.com/nsight-aftermath) 14 | * [NVIDIA R550 display driver or newer](https://www.nvidia.com/Download/index.aspx) 15 | * [Visual Studio 2022 or newer](https://www.visualstudio.com) 16 | 17 | On Linux 18 | 19 | * [CMake 3.17 or newer](https://cmake.org/download) 20 | * [Vulkan-SDK (1.2.135 or newer)](https://vulkan.lunarg.com/sdk/home) 21 | * [Nsight Aftermath SDK 2023.2 or newer](https://developer.nvidia.com/nsight-aftermath) 22 | * [NVIDIA R550 display driver or newer](https://www.nvidia.com/Download/index.aspx) 23 | * Officially tested on Ubuntu 22.04 and above 24 | 25 | ## Source Organization 26 | 27 | * `VkHelloNsightAftermath.cpp` 28 | * Main implementation file (device creation, resource creation, 29 | rendering). 30 | * All additions for Nsight Aftermath code instrumentation are guarded with 31 | `#if USE_NSIGHT_AFTERMATH`. To disable this instrumentation, ensure 32 | `USE_NSIGHT_AFTERMATH` is defined as `0` or is undefined. 33 | * `NsightAftermathGpuCrashTracker.cpp` 34 | * Implements a simple GPU crash dump tracker showing the use of the Nsight 35 | Aftermath API for collecting and decoding GPU crash dumps. 36 | * `NsightAftermathShaderDatabase.cpp` 37 | * Implements a very basic shader database as an example of how to provide 38 | shader binary data and shader debug data for shader instruction address 39 | mapping when decoding crash dumps. 40 | 41 | NOTE: this sample code implements GPU crash dump collection and decoding in a 42 | single application, but this is not the typical use case. Rather, users will 43 | typically split this into a GPU crash dump collection phase, integrated into 44 | the graphics application, and an offline decoding phase, implemented as an 45 | offline GPU crash dump analysis tool. 46 | 47 | ## Building the Sample 48 | 49 | On Windows 50 | 51 | * Install the Vulkan SDK on your platform and make sure the environment 52 | variable `VULKAN_SDK` is set. 53 | * Unpack the Nsight Aftermath SDK on your platform and make sure to set the 54 | `NSIGHT_AFTERMATH_SDK` environment variable to the directory containing the 55 | files. 56 | * Run CMake to generate your build files (for example, 57 | `cmake -G "Visual Studio 17 2022" -A x64 -S . -B .\Built`). 58 | * Build the VkHelloNsightAftermath target from the generated 59 | Visual Studio solution (`Built\VkHelloNsightAftermath.sln`) 60 | or use CMake build command `cmake --build .\Built --config Release`. 61 | 62 | On Linux 63 | 64 | * Install the Vulkan SDK on your platform and set up the `VULKAN_SDK` 65 | environment varible, e.g., run `source /setup-env.sh`. 66 | * Unpack the Nsight Aftermath SDK on your platform and make sure to set the 67 | `NSIGHT_AFTERMATH_SDK` environment variable to the directory containing the 68 | files. 69 | * Create a directory for the build artifacts under the VkHelloNsightAftermath 70 | directory, e.g. `mkdir built && cd built`. 71 | * Run `cmake .. && make` to generate the Makefile and build the 72 | VkHelloNsightAftermath executable. 73 | 74 | ## Running the Sample 75 | 76 | * On Windows, run `VkHelloNsightAftermath.exe`. 77 | * On Linux, run `./VkHelloNsightAftermath`. 78 | * The application will render a simple animated cube and will hang/TDR after 79 | a few seconds. 80 | * A GPU crash dump file (`VkHelloNsightAftermath--.nv-gpudmp`), 81 | a text file containing the GPU crash dump data decoded into JSON 82 | (`VkHelloNsightAftermath--.nv-gpudmp.json`) and a shader 83 | debug information file (`shader-.nvdbg`) will be created in the 84 | application's working directory. 85 | * Open the JSON file to inspect the data captured for the crash or use 86 | [Nsight Graphics](https://developer.nvidia.com/nsight-graphics) to open 87 | the GPU crash dump file. 88 | 89 | ## Copyright and Licenses 90 | 91 | cf. LICENSE file. 92 | 93 | This Code is based upon the `cube` demo from https://github.com/KhronosGroup/Vulkan-Tools/ (Copyright (c) 2015-2019 The Khronos Group Inc). 94 | 95 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/Copyright_cmake.txt: -------------------------------------------------------------------------------- 1 | CMake - Cross Platform Makefile Generator 2 | Copyright 2000-2018 Kitware, Inc. and Contributors 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | * Neither the name of Kitware, Inc. nor the names of Contributors 17 | may be used to endorse or promote products derived from this 18 | software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | ------------------------------------------------------------------------------ 33 | 34 | The following individuals and institutions are among the Contributors: 35 | 36 | * Aaron C. Meadows 37 | * Adriaan de Groot 38 | * Aleksey Avdeev 39 | * Alexander Neundorf 40 | * Alexander Smorkalov 41 | * Alexey Sokolov 42 | * Alex Turbov 43 | * Andreas Pakulat 44 | * Andreas Schneider 45 | * André Rigland Brodtkorb 46 | * Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf 47 | * Benjamin Eikel 48 | * Bjoern Ricks 49 | * Brad Hards 50 | * Christopher Harvey 51 | * Christoph Grüninger 52 | * Clement Creusot 53 | * Daniel Blezek 54 | * Daniel Pfeifer 55 | * Enrico Scholz 56 | * Eran Ifrah 57 | * Esben Mose Hansen, Ange Optimization ApS 58 | * Geoffrey Viola 59 | * Google Inc 60 | * Gregor Jasny 61 | * Helio Chissini de Castro 62 | * Ilya Lavrenov 63 | * Insight Software Consortium 64 | * Jan Woetzel 65 | * Kelly Thompson 66 | * Konstantin Podsvirov 67 | * Mario Bensi 68 | * Mathieu Malaterre 69 | * Matthaeus G. Chajdas 70 | * Matthias Kretz 71 | * Matthias Maennich 72 | * Michael Stürmer 73 | * Miguel A. Figueroa-Villanueva 74 | * Mike Jackson 75 | * Mike McQuaid 76 | * Nicolas Bock 77 | * Nicolas Despres 78 | * Nikita Krupen'ko 79 | * NVIDIA Corporation 80 | * OpenGamma Ltd. 81 | * Patrick Stotko 82 | * Per Øyvind Karlsen 83 | * Peter Collingbourne 84 | * Petr Gotthard 85 | * Philip Lowman 86 | * Philippe Proulx 87 | * Raffi Enficiaud, Max Planck Society 88 | * Raumfeld 89 | * Roger Leigh 90 | * Rolf Eike Beer 91 | * Roman Donchenko 92 | * Roman Kharitonov 93 | * Ruslan Baratov 94 | * Sebastian Holtermann 95 | * Stephen Kelly 96 | * Sylvain Joubert 97 | * Thomas Sondergaard 98 | * Tobias Hunger 99 | * Todd Gamblin 100 | * Tristan Carel 101 | * University of Dundee 102 | * Vadim Zhukov 103 | * Will Dicharry 104 | 105 | See version control history for details of individual contributions. 106 | 107 | The above copyright and license notice applies to distributions of 108 | CMake in source and binary form. Third-party software packages supplied 109 | with CMake under compatible licenses provide their own copyright notices 110 | documented in corresponding subdirectories or source files. 111 | 112 | ------------------------------------------------------------------------------ 113 | 114 | CMake was initially developed by Kitware with the following sponsorship: 115 | 116 | * National Library of Medicine at the National Institutes of Health 117 | as part of the Insight Segmentation and Registration Toolkit (ITK). 118 | 119 | * US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel 120 | Visualization Initiative. 121 | 122 | * National Alliance for Medical Image Computing (NAMIC) is funded by the 123 | National Institutes of Health through the NIH Roadmap for Medical Research, 124 | Grant U54 EB005149. 125 | 126 | * Kitware, Inc. 127 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindNsightAftermath.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 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 | #.rst: 17 | # FindNsightAftermath 18 | # ---------- 19 | # 20 | # Try to find the NVIDIA Nsight Aftermath SDK based on the NSIGHT_AFTERMATH_SDK environment variable 21 | # 22 | # IMPORTED Targets 23 | # ^^^^^^^^^^^^^^^^ 24 | # 25 | # This module defines :prop_tgt:`IMPORTED` target ``NsightAftermath::NsightAftermath``, if 26 | # the NVIDIA Nsight Aftermath SDK has been found. 27 | # 28 | # Result Variables 29 | # ^^^^^^^^^^^^^^^^ 30 | # 31 | # This module defines the following variables:: 32 | # 33 | # NsightAftermath_FOUND - True if the NVIDIA Nsight Aftermath SDK was found 34 | # NsightAftermath_INCLUDE_DIRS - include directories for the NVIDIA Nsight Aftermath SDK 35 | # NsightAftermath_LIBRARIES - link against this library to use the NVIDIA Nsight Aftermath SDK 36 | # 37 | # The module will also define two cache variables:: 38 | # 39 | # NsightAftermath_INCLUDE_DIR - the NVIDIA Nsight Aftermath SDK include directory 40 | # NsightAftermath_LIBRARY - the path to the NVIDIA Nsight Aftermath SDK library 41 | # 42 | 43 | if(WIN32 OR UNIX) 44 | find_path(NsightAftermath_INCLUDE_DIR 45 | NAMES GFSDK_Aftermath.h 46 | PATHS 47 | "$ENV{NSIGHT_AFTERMATH_SDK}/include" 48 | ) 49 | 50 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 51 | find_library(NsightAftermath_LIBRARY 52 | NAMES GFSDK_Aftermath_Lib.x64 53 | PATHS 54 | "$ENV{NSIGHT_AFTERMATH_SDK}/lib/x64" 55 | NO_SYSTEM_ENVIRONMENT_PATH 56 | ) 57 | if(WIN32) 58 | find_file(NsightAftermath_DLL 59 | NAMES GFSDK_Aftermath_Lib.x64.dll 60 | PATHS 61 | "$ENV{NSIGHT_AFTERMATH_SDK}/lib/x64" 62 | NO_SYSTEM_ENVIRONMENT_PATH 63 | ) 64 | endif() 65 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 66 | find_library(NsightAftermath_LIBRARY 67 | NAMES GFSDK_Aftermath_Lib.x86 68 | PATHS 69 | "$ENV{NSIGHT_AFTERMATH_SDK}/lib/x86" 70 | NO_SYSTEM_ENVIRONMENT_PATH 71 | ) 72 | if(WIN32) 73 | find_file(NsightAftermath_DLL 74 | NAMES GFSDK_Aftermath_Lib.x86.dll 75 | PATHS 76 | "$ENV{NSIGHT_AFTERMATH_SDK}/lib/x86" 77 | NO_SYSTEM_ENVIRONMENT_PATH 78 | ) 79 | endif() 80 | endif() 81 | else() 82 | find_path(NsightAftermath_INCLUDE_DIR 83 | NAMES GFSDK_Aftermath.h 84 | PATHS 85 | "$ENV{NSIGHT_AFTERMATH_SDK}/include") 86 | find_library(NsightAftermath_LIBRARY 87 | NAMES GFSDK_Aftermath_Lib 88 | PATHS 89 | "$ENV{NSIGHT_AFTERMATH_SDK}/lib") 90 | endif() 91 | 92 | set(NsightAftermath_LIBRARIES ${NsightAftermath_LIBRARY}) 93 | set(NsightAftermath_INCLUDE_DIRS ${NsightAftermath_INCLUDE_DIR}) 94 | 95 | include(FindPackageHandleStandardArgs) 96 | find_package_handle_standard_args(NsightAftermath 97 | DEFAULT_MSG 98 | NsightAftermath_LIBRARY NsightAftermath_INCLUDE_DIR) 99 | 100 | mark_as_advanced(NsightAftermath_INCLUDE_DIR NsightAftermath_LIBRARY) 101 | 102 | if(NsightAftermath_FOUND AND NOT TARGET NsightAftermath::NsightAftermath) 103 | add_library(NsightAftermath::NsightAftermath UNKNOWN IMPORTED) 104 | set_target_properties(NsightAftermath::NsightAftermath PROPERTIES 105 | IMPORTED_LOCATION "${NsightAftermath_LIBRARIES}" 106 | INTERFACE_INCLUDE_DIRECTORIES "${NsightAftermath_INCLUDE_DIRS}") 107 | endif() 108 | 109 | if(NOT NsightAftermath_FOUND) 110 | if(DEFINED ENV{NSIGHT_AFTERMATH_SDK}) 111 | message("NSIGHT_AFTERMATH_SDK environment variable not set to a valid location (is $ENV{NSIGHT_AFTERMATH_SDK})") 112 | else() 113 | message("NSIGHT_AFTERMATH_SDK environment variable not set") 114 | endif() 115 | endif() 116 | 117 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindVulkan.cmake: -------------------------------------------------------------------------------- 1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2 | # file Copyright.txt or https://cmake.org/licensing for details. 3 | 4 | #.rst: 5 | # FindVulkan 6 | # ---------- 7 | # 8 | # Try to find Vulkan 9 | # 10 | # IMPORTED Targets 11 | # ^^^^^^^^^^^^^^^^ 12 | # 13 | # This module defines :prop_tgt:`IMPORTED` target ``Vulkan::Vulkan``, if 14 | # Vulkan has been found. 15 | # 16 | # Result Variables 17 | # ^^^^^^^^^^^^^^^^ 18 | # 19 | # This module defines the following variables:: 20 | # 21 | # Vulkan_FOUND - True if Vulkan was found 22 | # Vulkan_INCLUDE_DIRS - include directories for Vulkan 23 | # Vulkan_LIBRARIES - link against this library to use Vulkan 24 | # 25 | # The module will also define two cache variables:: 26 | # 27 | # Vulkan_INCLUDE_DIR - the Vulkan include directory 28 | # Vulkan_LIBRARY - the path to the Vulkan library 29 | # 30 | 31 | if(WIN32) 32 | find_path(Vulkan_INCLUDE_DIR 33 | NAMES vulkan/vulkan.h 34 | PATHS 35 | "$ENV{VULKAN_SDK}/Include" 36 | ) 37 | 38 | if(CMAKE_SIZEOF_VOID_P EQUAL 8) 39 | find_library(Vulkan_LIBRARY 40 | NAMES vulkan-1 41 | PATHS 42 | "$ENV{VULKAN_SDK}/Lib" 43 | "$ENV{VULKAN_SDK}/Bin" 44 | ) 45 | elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) 46 | find_library(Vulkan_LIBRARY 47 | NAMES vulkan-1 48 | PATHS 49 | "$ENV{VULKAN_SDK}/Lib32" 50 | "$ENV{VULKAN_SDK}/Bin32" 51 | NO_SYSTEM_ENVIRONMENT_PATH 52 | ) 53 | endif() 54 | else() 55 | find_path(Vulkan_INCLUDE_DIR 56 | NAMES vulkan/vulkan.h 57 | PATHS 58 | "$ENV{VULKAN_SDK}/include") 59 | find_library(Vulkan_LIBRARY 60 | NAMES vulkan 61 | PATHS 62 | "$ENV{VULKAN_SDK}/lib") 63 | endif() 64 | 65 | set(Vulkan_LIBRARIES ${Vulkan_LIBRARY}) 66 | set(Vulkan_INCLUDE_DIRS ${Vulkan_INCLUDE_DIR}) 67 | 68 | include(FindPackageHandleStandardArgs) 69 | find_package_handle_standard_args(Vulkan 70 | DEFAULT_MSG 71 | Vulkan_LIBRARY Vulkan_INCLUDE_DIR) 72 | 73 | mark_as_advanced(Vulkan_INCLUDE_DIR Vulkan_LIBRARY) 74 | 75 | if(Vulkan_FOUND AND NOT TARGET Vulkan::Vulkan) 76 | add_library(Vulkan::Vulkan UNKNOWN IMPORTED) 77 | set_target_properties(Vulkan::Vulkan PROPERTIES 78 | IMPORTED_LOCATION "${Vulkan_LIBRARIES}" 79 | INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") 80 | endif() 81 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindVulkanHeaders.cmake: -------------------------------------------------------------------------------- 1 | #.rst: 2 | # FindVulkanHeaders 3 | # ----------------- 4 | # 5 | # Try to find Vulkan Headers and Registry. 6 | # 7 | # This module is intended to be used by projects that build Vulkan 8 | # "system" components such as the loader and layers. 9 | # Vulkan applications should instead use the FindVulkan (or similar) 10 | # find module that locates the headers and the loader library. 11 | # 12 | # When using this find module to locate the headers and registry 13 | # in a Vulkan-Headers repository, the Vulkan-Headers repository 14 | # should be built with 'install' target and the following environment 15 | # or CMake variable set to the location of the install directory. 16 | # 17 | # VULKAN_HEADERS_INSTALL_DIR 18 | # 19 | # IMPORTED Targets 20 | # ^^^^^^^^^^^^^^^^ 21 | # 22 | # This module defines no IMPORTED targets 23 | # 24 | # Result Variables 25 | # ^^^^^^^^^^^^^^^^ 26 | # 27 | # This module defines the following variables:: 28 | # 29 | # VulkanHeaders_FOUND - True if VulkanHeaders was found 30 | # VulkanHeaders_INCLUDE_DIRS - include directories for VulkanHeaders 31 | # 32 | # VulkanRegistry_FOUND - True if VulkanRegistry was found 33 | # VulkanRegistry_DIRS - directories for VulkanRegistry 34 | # 35 | # The module will also define two cache variables:: 36 | # 37 | # VulkanHeaders_INCLUDE_DIR - the VulkanHeaders include directory 38 | # VulkanRegistry_DIR - the VulkanRegistry directory 39 | # 40 | 41 | # Use HINTS instead of PATH to search these locations before 42 | # searching system environment variables like $PATH that may 43 | # contain SDK directories. 44 | find_path(VulkanHeaders_INCLUDE_DIR 45 | NAMES vulkan/vulkan.h 46 | HINTS 47 | ${VULKAN_HEADERS_INSTALL_DIR}/include 48 | "$ENV{VULKAN_HEADERS_INSTALL_DIR}/include" 49 | "$ENV{VULKAN_SDK}/include") 50 | 51 | if(VulkanHeaders_INCLUDE_DIR) 52 | get_filename_component(VULKAN_REGISTRY_PATH_HINT ${VulkanHeaders_INCLUDE_DIR} DIRECTORY) 53 | find_path(VulkanRegistry_DIR 54 | NAMES vk.xml 55 | HINTS "${VULKAN_REGISTRY_PATH_HINT}/share/vulkan/registry") 56 | endif() 57 | 58 | set(VulkanHeaders_INCLUDE_DIRS ${VulkanHeaders_INCLUDE_DIR}) 59 | set(VulkanRegistry_DIRS ${VulkanRegistry_DIR}) 60 | 61 | include(FindPackageHandleStandardArgs) 62 | find_package_handle_standard_args(VulkanHeaders 63 | DEFAULT_MSG 64 | VulkanHeaders_INCLUDE_DIR) 65 | 66 | find_package_handle_standard_args(VulkanRegistry 67 | REQUIRED_VARS VulkanRegistry_DIR 68 | NAME_MISMATCHED) 69 | 70 | mark_as_advanced(VulkanHeaders_INCLUDE_DIR VulkanRegistry_DIR) 71 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindWayland.cmake: -------------------------------------------------------------------------------- 1 | # Try to find Wayland on a Unix system 2 | # 3 | # This will define: 4 | # 5 | # WAYLAND_FOUND - True if Wayland is found 6 | # WAYLAND_LIBRARIES - Link these to use Wayland 7 | # WAYLAND_INCLUDE_DIR - Include directory for Wayland 8 | # WAYLAND_DEFINITIONS - Compiler flags for using Wayland 9 | # 10 | # In addition the following more fine grained variables will be defined: 11 | # 12 | # WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES 13 | # WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES 14 | # WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES 15 | # 16 | # Copyright (c) 2013 Martin Gräßlin 17 | # 18 | # Redistribution and use is allowed according to the terms of the BSD license. 19 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 20 | 21 | IF (NOT WIN32) 22 | IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES) 23 | # In the cache already 24 | SET(WAYLAND_FIND_QUIETLY TRUE) 25 | ENDIF () 26 | 27 | # Use pkg-config to get the directories and then use these values 28 | # in the FIND_PATH() and FIND_LIBRARY() calls 29 | FIND_PACKAGE(PkgConfig) 30 | PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) 31 | 32 | SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) 33 | 34 | FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 35 | FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 36 | FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 37 | FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) 38 | 39 | FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 40 | FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 41 | FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 42 | FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) 43 | 44 | set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) 45 | 46 | set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) 47 | 48 | list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) 49 | 50 | include(FindPackageHandleStandardArgs) 51 | 52 | find_package_handle_standard_args(WAYLAND_CLIENT 53 | REQUIRED_VARS WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR 54 | NAME_MISMATCHED) 55 | find_package_handle_standard_args(WAYLAND_SERVER 56 | REQUIRED_VARS WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR 57 | NAME_MISMATCHED) 58 | find_package_handle_standard_args(WAYLAND_EGL 59 | REQUIRED_VARS WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR 60 | NAME_MISMATCHED) 61 | find_package_handle_standard_args(WAYLAND_CURSOR 62 | REQUIRED_VARS WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR 63 | NAME_MISMATCHED) 64 | find_package_handle_standard_args(WAYLAND # Main package, still use NAME_MISMATCHED for potential case issues 65 | REQUIRED_VARS WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR 66 | NAME_MISMATCHED) 67 | 68 | MARK_AS_ADVANCED( 69 | WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES 70 | WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES 71 | WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES 72 | WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES 73 | WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES 74 | ) 75 | 76 | ENDIF () 77 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindX11_XCB.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find libX11-xcb 2 | # Once done this will define 3 | # 4 | # X11_XCB_FOUND - system has libX11-xcb 5 | # X11_XCB_LIBRARIES - Link these to use libX11-xcb 6 | # X11_XCB_INCLUDE_DIR - the libX11-xcb include dir 7 | # X11_XCB_DEFINITIONS - compiler switches required for using libX11-xcb 8 | 9 | # Copyright (c) 2011 Fredrik Höglund 10 | # Copyright (c) 2008 Helio Chissini de Castro, 11 | # Copyright (c) 2007 Matthias Kretz, 12 | # 13 | # Redistribution and use is allowed according to the terms of the BSD license. 14 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 15 | 16 | IF (NOT WIN32) 17 | # use pkg-config to get the directories and then use these values 18 | # in the FIND_PATH() and FIND_LIBRARY() calls 19 | FIND_PACKAGE(PkgConfig) 20 | PKG_CHECK_MODULES(PKG_X11_XCB QUIET x11-xcb) 21 | 22 | SET(X11_XCB_DEFINITIONS ${PKG_X11_XCB_CFLAGS}) 23 | 24 | FIND_PATH(X11_XCB_INCLUDE_DIR NAMES X11/Xlib-xcb.h HINTS ${PKG_X11_XCB_INCLUDE_DIRS}) 25 | FIND_LIBRARY(X11_XCB_LIBRARIES NAMES X11-xcb HINTS ${PKG_X11_XCB_LIBRARY_DIRS}) 26 | 27 | include(FindPackageHandleStandardArgs) 28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11_XCB DEFAULT_MSG X11_XCB_LIBRARIES X11_XCB_INCLUDE_DIR) 29 | 30 | MARK_AS_ADVANCED(X11_XCB_INCLUDE_DIR X11_XCB_LIBRARIES) 31 | ENDIF (NOT WIN32) 32 | 33 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cmake/FindXCB.cmake: -------------------------------------------------------------------------------- 1 | # - FindXCB 2 | # 3 | # Copyright (C) 2015 Valve Corporation 4 | 5 | find_package(PkgConfig) 6 | 7 | if(NOT XCB_FIND_COMPONENTS) 8 | set(XCB_FIND_COMPONENTS xcb) 9 | endif() 10 | 11 | include(FindPackageHandleStandardArgs) 12 | set(XCB_FOUND true) 13 | set(XCB_INCLUDE_DIRS "") 14 | set(XCB_LIBRARIES "") 15 | foreach(comp ${XCB_FIND_COMPONENTS}) 16 | # component name 17 | string(TOUPPER ${comp} compname) 18 | string(REPLACE "-" "_" compname ${compname}) 19 | # header name 20 | string(REPLACE "xcb-" "" headername xcb/${comp}.h) 21 | # library name 22 | set(libname ${comp}) 23 | 24 | pkg_check_modules(PC_${comp} QUIET ${comp}) 25 | 26 | find_path(${compname}_INCLUDE_DIR NAMES ${headername} 27 | HINTS 28 | ${PC_${comp}_INCLUDEDIR} 29 | ${PC_${comp}_INCLUDE_DIRS} 30 | ) 31 | 32 | find_library(${compname}_LIBRARY NAMES ${libname} 33 | HINTS 34 | ${PC_${comp}_LIBDIR} 35 | ${PC_${comp}_LIBRARY_DIRS} 36 | ) 37 | 38 | find_package_handle_standard_args(${comp} 39 | REQUIRED_VARS ${compname}_INCLUDE_DIR ${compname}_LIBRARY 40 | NAME_MISMATCHED) 41 | mark_as_advanced(${compname}_INCLUDE_DIR ${compname}_LIBRARY) 42 | 43 | list(APPEND XCB_INCLUDE_DIRS ${${compname}_INCLUDE_DIR}) 44 | list(APPEND XCB_LIBRARIES ${${compname}_LIBRARY}) 45 | 46 | if(NOT ${comp}_FOUND) 47 | set(XCB_FOUND false) 48 | endif() 49 | endforeach() 50 | 51 | list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS) 52 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cube.frag: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016 The Khronos Group Inc. 3 | * Copyright (c) 2015-2016 Valve Corporation 4 | * Copyright (c) 2015-2016 LunarG, Inc. 5 | * Copyright (c) 2019 NVIDIA Corporation 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | /* 20 | * Fragment shader for cube demo 21 | */ 22 | #version 400 23 | #extension GL_ARB_separate_shader_objects : enable 24 | #extension GL_ARB_shading_language_420pack : enable 25 | layout (binding = 1) uniform sampler2D tex; 26 | 27 | layout (location = 0) in vec4 texcoord; 28 | layout (location = 1) in vec3 frag_pos; 29 | layout (location = 2) in float alpha; 30 | layout (location = 0) out vec4 uFragColor; 31 | 32 | const vec3 lightDir= vec3(0.424, 0.566, 0.707); 33 | 34 | void main() { 35 | vec3 dX = dFdx(frag_pos); 36 | vec3 dY = dFdy(frag_pos); 37 | vec3 normal = normalize(cross(dX,dY)); 38 | float light = max(0.0, dot(lightDir, normal)) * (1.0 - alpha); 39 | uFragColor = light * texture(tex, texcoord.xy); 40 | } 41 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/cube.vert: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016 The Khronos Group Inc. 3 | * Copyright (c) 2015-2016 Valve Corporation 4 | * Copyright (c) 2015-2016 LunarG, Inc. 5 | * Copyright (c) 2019 NVIDIA Corporation 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | /* 20 | * Vertex shader used by Cube demo. 21 | */ 22 | #version 400 23 | #extension GL_ARB_separate_shader_objects : enable 24 | #extension GL_ARB_shading_language_420pack : enable 25 | layout(std140, binding = 0) uniform buf { 26 | mat4 MVP; 27 | vec4 position[12*3]; 28 | vec4 attr[12*3]; 29 | vec4 offset; 30 | } ubuf; 31 | 32 | layout (location = 0) out vec4 texcoord; 33 | layout (location = 1) out vec3 frag_pos; 34 | layout (location = 2) out float alpha; 35 | 36 | #define ENDLESSLOOP_VS 1 37 | 38 | void main() 39 | { 40 | texcoord = ubuf.attr[gl_VertexIndex]; 41 | gl_Position = ubuf.MVP * (ubuf.position[gl_VertexIndex] + ubuf.offset); 42 | frag_pos = gl_Position.xyz; 43 | alpha = 1.0; 44 | #if ENDLESSLOOP_VS 45 | while (alpha > 0.0) 46 | { 47 | alpha -= ubuf.offset.x; 48 | } 49 | alpha *= 0.1 * alpha; 50 | #endif 51 | } 52 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/gettime.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 3 | * Copyright 2014, 2017 The Android Open Source Project 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 | * Ported from drawElements Utility Library (Google, Inc.) 18 | * Port done by: Ian Elliott 19 | **************************************************************************/ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #if defined(_WIN32) 26 | 27 | #include 28 | 29 | #elif defined(__unix__) || defined(__linux) || defined(__linux__) || defined(__ANDROID__) || defined(__EPOC32__) || defined(__QNX__) 30 | 31 | #include 32 | 33 | #elif defined(__APPLE__) 34 | 35 | #include 36 | 37 | #endif 38 | 39 | uint64_t getTimeInNanoseconds(void) { 40 | #if defined(_WIN32) 41 | LARGE_INTEGER freq; 42 | LARGE_INTEGER count; 43 | QueryPerformanceCounter(&count); 44 | QueryPerformanceFrequency(&freq); 45 | assert(freq.LowPart != 0 || freq.HighPart != 0); 46 | 47 | if (count.QuadPart < MAXLONGLONG / 1000000) { 48 | assert(freq.QuadPart != 0); 49 | return count.QuadPart * 1000000 / freq.QuadPart; 50 | } else { 51 | assert(freq.QuadPart >= 1000000); 52 | return count.QuadPart / (freq.QuadPart / 1000000); 53 | } 54 | 55 | #elif defined(__unix__) || defined(__linux) || defined(__linux__) || defined(__ANDROID__) || defined(__QNX__) 56 | struct timespec currTime; 57 | clock_gettime(CLOCK_MONOTONIC, &currTime); 58 | return (uint64_t)currTime.tv_sec * 1000000 + ((uint64_t)currTime.tv_nsec / 1000); 59 | 60 | #elif defined(__EPOC32__) 61 | struct timespec currTime; 62 | /* Symbian supports only realtime clock for clock_gettime. */ 63 | clock_gettime(CLOCK_REALTIME, &currTime); 64 | return (uint64_t)currTime.tv_sec * 1000000 + ((uint64_t)currTime.tv_nsec / 1000); 65 | 66 | #elif defined(__APPLE__) 67 | struct timeval currTime; 68 | gettimeofday(&currTime, NULL); 69 | return (uint64_t)currTime.tv_sec * 1000000 + (uint64_t)currTime.tv_usec; 70 | 71 | #else 72 | #error "Not implemented for target OS" 73 | #endif 74 | } 75 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/linmath.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015-2016 The Khronos Group Inc. 3 | * Copyright (c) 2015-2016 Valve Corporation 4 | * Copyright (c) 2015-2016 LunarG, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Relicensed from the WTFPL (http://www.wtfpl.net/faq/). 19 | */ 20 | 21 | #ifndef LINMATH_H 22 | #define LINMATH_H 23 | 24 | #include 25 | 26 | // Converts degrees to radians. 27 | #define degreesToRadians(angleDegrees) (angleDegrees * M_PI / 180.0) 28 | 29 | // Converts radians to degrees. 30 | #define radiansToDegrees(angleRadians) (angleRadians * 180.0 / M_PI) 31 | 32 | typedef float vec3[3]; 33 | static inline void vec3_add(vec3 r, vec3 const a, vec3 const b) { 34 | int i; 35 | for (i = 0; i < 3; ++i) r[i] = a[i] + b[i]; 36 | } 37 | static inline void vec3_sub(vec3 r, vec3 const a, vec3 const b) { 38 | int i; 39 | for (i = 0; i < 3; ++i) r[i] = a[i] - b[i]; 40 | } 41 | static inline void vec3_scale(vec3 r, vec3 const v, float const s) { 42 | int i; 43 | for (i = 0; i < 3; ++i) r[i] = v[i] * s; 44 | } 45 | static inline float vec3_mul_inner(vec3 const a, vec3 const b) { 46 | float p = 0.f; 47 | int i; 48 | for (i = 0; i < 3; ++i) p += b[i] * a[i]; 49 | return p; 50 | } 51 | static inline void vec3_mul_cross(vec3 r, vec3 const a, vec3 const b) { 52 | r[0] = a[1] * b[2] - a[2] * b[1]; 53 | r[1] = a[2] * b[0] - a[0] * b[2]; 54 | r[2] = a[0] * b[1] - a[1] * b[0]; 55 | } 56 | static inline float vec3_len(vec3 const v) { return sqrtf(vec3_mul_inner(v, v)); } 57 | static inline void vec3_norm(vec3 r, vec3 const v) { 58 | float k = 1.f / vec3_len(v); 59 | vec3_scale(r, v, k); 60 | } 61 | static inline void vec3_reflect(vec3 r, vec3 const v, vec3 const n) { 62 | float p = 2.f * vec3_mul_inner(v, n); 63 | int i; 64 | for (i = 0; i < 3; ++i) r[i] = v[i] - p * n[i]; 65 | } 66 | 67 | typedef float vec4[4]; 68 | static inline void vec4_add(vec4 r, vec4 const a, vec4 const b) { 69 | int i; 70 | for (i = 0; i < 4; ++i) r[i] = a[i] + b[i]; 71 | } 72 | static inline void vec4_sub(vec4 r, vec4 const a, vec4 const b) { 73 | int i; 74 | for (i = 0; i < 4; ++i) r[i] = a[i] - b[i]; 75 | } 76 | static inline void vec4_scale(vec4 r, vec4 v, float s) { 77 | int i; 78 | for (i = 0; i < 4; ++i) r[i] = v[i] * s; 79 | } 80 | static inline float vec4_mul_inner(vec4 a, vec4 b) { 81 | float p = 0.f; 82 | int i; 83 | for (i = 0; i < 4; ++i) p += b[i] * a[i]; 84 | return p; 85 | } 86 | static inline void vec4_mul_cross(vec4 r, vec4 a, vec4 b) { 87 | r[0] = a[1] * b[2] - a[2] * b[1]; 88 | r[1] = a[2] * b[0] - a[0] * b[2]; 89 | r[2] = a[0] * b[1] - a[1] * b[0]; 90 | r[3] = 1.f; 91 | } 92 | static inline float vec4_len(vec4 v) { return sqrtf(vec4_mul_inner(v, v)); } 93 | static inline void vec4_norm(vec4 r, vec4 v) { 94 | float k = 1.f / vec4_len(v); 95 | vec4_scale(r, v, k); 96 | } 97 | static inline void vec4_reflect(vec4 r, vec4 v, vec4 n) { 98 | float p = 2.f * vec4_mul_inner(v, n); 99 | int i; 100 | for (i = 0; i < 4; ++i) r[i] = v[i] - p * n[i]; 101 | } 102 | 103 | typedef vec4 mat4x4[4]; 104 | static inline void mat4x4_identity(mat4x4 M) { 105 | int i, j; 106 | for (i = 0; i < 4; ++i) 107 | for (j = 0; j < 4; ++j) M[i][j] = i == j ? 1.f : 0.f; 108 | } 109 | static inline void mat4x4_dup(mat4x4 M, mat4x4 N) { 110 | int i, j; 111 | for (i = 0; i < 4; ++i) 112 | for (j = 0; j < 4; ++j) M[i][j] = N[i][j]; 113 | } 114 | static inline void mat4x4_row(vec4 r, mat4x4 M, int i) { 115 | int k; 116 | for (k = 0; k < 4; ++k) r[k] = M[k][i]; 117 | } 118 | static inline void mat4x4_col(vec4 r, mat4x4 M, int i) { 119 | int k; 120 | for (k = 0; k < 4; ++k) r[k] = M[i][k]; 121 | } 122 | static inline void mat4x4_transpose(mat4x4 M, mat4x4 N) { 123 | int i, j; 124 | for (j = 0; j < 4; ++j) 125 | for (i = 0; i < 4; ++i) M[i][j] = N[j][i]; 126 | } 127 | static inline void mat4x4_add(mat4x4 M, mat4x4 a, mat4x4 b) { 128 | int i; 129 | for (i = 0; i < 4; ++i) vec4_add(M[i], a[i], b[i]); 130 | } 131 | static inline void mat4x4_sub(mat4x4 M, mat4x4 a, mat4x4 b) { 132 | int i; 133 | for (i = 0; i < 4; ++i) vec4_sub(M[i], a[i], b[i]); 134 | } 135 | static inline void mat4x4_scale(mat4x4 M, mat4x4 a, float k) { 136 | int i; 137 | for (i = 0; i < 4; ++i) vec4_scale(M[i], a[i], k); 138 | } 139 | static inline void mat4x4_scale_aniso(mat4x4 M, mat4x4 a, float x, float y, float z) { 140 | int i; 141 | vec4_scale(M[0], a[0], x); 142 | vec4_scale(M[1], a[1], y); 143 | vec4_scale(M[2], a[2], z); 144 | for (i = 0; i < 4; ++i) { 145 | M[3][i] = a[3][i]; 146 | } 147 | } 148 | static inline void mat4x4_mul(mat4x4 M, mat4x4 a, mat4x4 b) { 149 | int k, r, c; 150 | for (c = 0; c < 4; ++c) 151 | for (r = 0; r < 4; ++r) { 152 | M[c][r] = 0.f; 153 | for (k = 0; k < 4; ++k) M[c][r] += a[k][r] * b[c][k]; 154 | } 155 | } 156 | static inline void mat4x4_mul_vec4(vec4 r, mat4x4 M, vec4 v) { 157 | int i, j; 158 | for (j = 0; j < 4; ++j) { 159 | r[j] = 0.f; 160 | for (i = 0; i < 4; ++i) r[j] += M[i][j] * v[i]; 161 | } 162 | } 163 | static inline void mat4x4_translate(mat4x4 T, float x, float y, float z) { 164 | mat4x4_identity(T); 165 | T[3][0] = x; 166 | T[3][1] = y; 167 | T[3][2] = z; 168 | } 169 | static inline void mat4x4_translate_in_place(mat4x4 M, float x, float y, float z) { 170 | vec4 t = {x, y, z, 0}; 171 | vec4 r; 172 | int i; 173 | for (i = 0; i < 4; ++i) { 174 | mat4x4_row(r, M, i); 175 | M[3][i] += vec4_mul_inner(r, t); 176 | } 177 | } 178 | static inline void mat4x4_from_vec3_mul_outer(mat4x4 M, vec3 a, vec3 b) { 179 | int i, j; 180 | for (i = 0; i < 4; ++i) 181 | for (j = 0; j < 4; ++j) M[i][j] = i < 3 && j < 3 ? a[i] * b[j] : 0.f; 182 | } 183 | static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z, float angle) { 184 | float s = sinf(angle); 185 | float c = cosf(angle); 186 | vec3 u = {x, y, z}; 187 | 188 | if (vec3_len(u) > 1e-4) { 189 | vec3_norm(u, u); 190 | mat4x4 T; 191 | mat4x4_from_vec3_mul_outer(T, u, u); 192 | 193 | mat4x4 S = {{0, u[2], -u[1], 0}, {-u[2], 0, u[0], 0}, {u[1], -u[0], 0, 0}, {0, 0, 0, 0}}; 194 | mat4x4_scale(S, S, s); 195 | 196 | mat4x4 C; 197 | mat4x4_identity(C); 198 | mat4x4_sub(C, C, T); 199 | 200 | mat4x4_scale(C, C, c); 201 | 202 | mat4x4_add(T, T, C); 203 | mat4x4_add(T, T, S); 204 | 205 | T[3][3] = 1.; 206 | mat4x4_mul(R, M, T); 207 | } else { 208 | mat4x4_dup(R, M); 209 | } 210 | } 211 | static inline void mat4x4_rotate_X(mat4x4 Q, mat4x4 M, float angle) { 212 | float s = sinf(angle); 213 | float c = cosf(angle); 214 | mat4x4 R = {{1.f, 0.f, 0.f, 0.f}, {0.f, c, s, 0.f}, {0.f, -s, c, 0.f}, {0.f, 0.f, 0.f, 1.f}}; 215 | mat4x4_mul(Q, M, R); 216 | } 217 | static inline void mat4x4_rotate_Y(mat4x4 Q, mat4x4 M, float angle) { 218 | float s = sinf(angle); 219 | float c = cosf(angle); 220 | mat4x4 R = {{c, 0.f, s, 0.f}, {0.f, 1.f, 0.f, 0.f}, {-s, 0.f, c, 0.f}, {0.f, 0.f, 0.f, 1.f}}; 221 | mat4x4_mul(Q, M, R); 222 | } 223 | static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle) { 224 | float s = sinf(angle); 225 | float c = cosf(angle); 226 | mat4x4 R = {{c, s, 0.f, 0.f}, {-s, c, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}}; 227 | mat4x4_mul(Q, M, R); 228 | } 229 | static inline void mat4x4_invert(mat4x4 T, mat4x4 M) { 230 | float s[6]; 231 | float c[6]; 232 | s[0] = M[0][0] * M[1][1] - M[1][0] * M[0][1]; 233 | s[1] = M[0][0] * M[1][2] - M[1][0] * M[0][2]; 234 | s[2] = M[0][0] * M[1][3] - M[1][0] * M[0][3]; 235 | s[3] = M[0][1] * M[1][2] - M[1][1] * M[0][2]; 236 | s[4] = M[0][1] * M[1][3] - M[1][1] * M[0][3]; 237 | s[5] = M[0][2] * M[1][3] - M[1][2] * M[0][3]; 238 | 239 | c[0] = M[2][0] * M[3][1] - M[3][0] * M[2][1]; 240 | c[1] = M[2][0] * M[3][2] - M[3][0] * M[2][2]; 241 | c[2] = M[2][0] * M[3][3] - M[3][0] * M[2][3]; 242 | c[3] = M[2][1] * M[3][2] - M[3][1] * M[2][2]; 243 | c[4] = M[2][1] * M[3][3] - M[3][1] * M[2][3]; 244 | c[5] = M[2][2] * M[3][3] - M[3][2] * M[2][3]; 245 | 246 | /* Assumes it is invertible */ 247 | float idet = 1.0f / (s[0] * c[5] - s[1] * c[4] + s[2] * c[3] + s[3] * c[2] - s[4] * c[1] + s[5] * c[0]); 248 | 249 | T[0][0] = (M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet; 250 | T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet; 251 | T[0][2] = (M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet; 252 | T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet; 253 | 254 | T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet; 255 | T[1][1] = (M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet; 256 | T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet; 257 | T[1][3] = (M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet; 258 | 259 | T[2][0] = (M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet; 260 | T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet; 261 | T[2][2] = (M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet; 262 | T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet; 263 | 264 | T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet; 265 | T[3][1] = (M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet; 266 | T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet; 267 | T[3][3] = (M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet; 268 | } 269 | static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M) { 270 | mat4x4_dup(R, M); 271 | float s = 1.; 272 | vec3 h; 273 | 274 | vec3_norm(R[2], R[2]); 275 | 276 | s = vec3_mul_inner(R[1], R[2]); 277 | vec3_scale(h, R[2], s); 278 | vec3_sub(R[1], R[1], h); 279 | vec3_norm(R[2], R[2]); 280 | 281 | s = vec3_mul_inner(R[1], R[2]); 282 | vec3_scale(h, R[2], s); 283 | vec3_sub(R[1], R[1], h); 284 | vec3_norm(R[1], R[1]); 285 | 286 | s = vec3_mul_inner(R[0], R[1]); 287 | vec3_scale(h, R[1], s); 288 | vec3_sub(R[0], R[0], h); 289 | vec3_norm(R[0], R[0]); 290 | } 291 | 292 | static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f) { 293 | M[0][0] = 2.f * n / (r - l); 294 | M[0][1] = M[0][2] = M[0][3] = 0.f; 295 | 296 | M[1][1] = 2.f * n / (t - b); 297 | M[1][0] = M[1][2] = M[1][3] = 0.f; 298 | 299 | M[2][0] = (r + l) / (r - l); 300 | M[2][1] = (t + b) / (t - b); 301 | M[2][2] = -(f + n) / (f - n); 302 | M[2][3] = -1.f; 303 | 304 | M[3][2] = -2.f * (f * n) / (f - n); 305 | M[3][0] = M[3][1] = M[3][3] = 0.f; 306 | } 307 | static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f) { 308 | M[0][0] = 2.f / (r - l); 309 | M[0][1] = M[0][2] = M[0][3] = 0.f; 310 | 311 | M[1][1] = 2.f / (t - b); 312 | M[1][0] = M[1][2] = M[1][3] = 0.f; 313 | 314 | M[2][2] = -2.f / (f - n); 315 | M[2][0] = M[2][1] = M[2][3] = 0.f; 316 | 317 | M[3][0] = -(r + l) / (r - l); 318 | M[3][1] = -(t + b) / (t - b); 319 | M[3][2] = -(f + n) / (f - n); 320 | M[3][3] = 1.f; 321 | } 322 | static inline void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f) { 323 | /* NOTE: Degrees are an unhandy unit to work with. 324 | * linmath.h uses radians for everything! */ 325 | float const a = (float)(1.f / tan(y_fov / 2.f)); 326 | 327 | m[0][0] = a / aspect; 328 | m[0][1] = 0.f; 329 | m[0][2] = 0.f; 330 | m[0][3] = 0.f; 331 | 332 | m[1][0] = 0.f; 333 | m[1][1] = a; 334 | m[1][2] = 0.f; 335 | m[1][3] = 0.f; 336 | 337 | m[2][0] = 0.f; 338 | m[2][1] = 0.f; 339 | m[2][2] = -((f + n) / (f - n)); 340 | m[2][3] = -1.f; 341 | 342 | m[3][0] = 0.f; 343 | m[3][1] = 0.f; 344 | m[3][2] = -((2.f * f * n) / (f - n)); 345 | m[3][3] = 0.f; 346 | } 347 | static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up) { 348 | /* Adapted from Android's OpenGL Matrix.java. */ 349 | /* See the OpenGL GLUT documentation for gluLookAt for a description */ 350 | /* of the algorithm. We implement it in a straightforward way: */ 351 | 352 | /* TODO: The negation of of can be spared by swapping the order of 353 | * operands in the following cross products in the right way. */ 354 | vec3 f; 355 | vec3_sub(f, center, eye); 356 | vec3_norm(f, f); 357 | 358 | vec3 s; 359 | vec3_mul_cross(s, f, up); 360 | vec3_norm(s, s); 361 | 362 | vec3 t; 363 | vec3_mul_cross(t, s, f); 364 | 365 | m[0][0] = s[0]; 366 | m[0][1] = t[0]; 367 | m[0][2] = -f[0]; 368 | m[0][3] = 0.f; 369 | 370 | m[1][0] = s[1]; 371 | m[1][1] = t[1]; 372 | m[1][2] = -f[1]; 373 | m[1][3] = 0.f; 374 | 375 | m[2][0] = s[2]; 376 | m[2][1] = t[2]; 377 | m[2][2] = -f[2]; 378 | m[2][3] = 0.f; 379 | 380 | m[3][0] = 0.f; 381 | m[3][1] = 0.f; 382 | m[3][2] = 0.f; 383 | m[3][3] = 1.f; 384 | 385 | mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]); 386 | } 387 | 388 | typedef float quat[4]; 389 | static inline void quat_identity(quat q) { 390 | q[0] = q[1] = q[2] = 0.f; 391 | q[3] = 1.f; 392 | } 393 | static inline void quat_add(quat r, quat a, quat b) { 394 | int i; 395 | for (i = 0; i < 4; ++i) r[i] = a[i] + b[i]; 396 | } 397 | static inline void quat_sub(quat r, quat a, quat b) { 398 | int i; 399 | for (i = 0; i < 4; ++i) r[i] = a[i] - b[i]; 400 | } 401 | static inline void quat_mul(quat r, quat p, quat q) { 402 | vec3 w; 403 | vec3_mul_cross(r, p, q); 404 | vec3_scale(w, p, q[3]); 405 | vec3_add(r, r, w); 406 | vec3_scale(w, q, p[3]); 407 | vec3_add(r, r, w); 408 | r[3] = p[3] * q[3] - vec3_mul_inner(p, q); 409 | } 410 | static inline void quat_scale(quat r, quat v, float s) { 411 | int i; 412 | for (i = 0; i < 4; ++i) r[i] = v[i] * s; 413 | } 414 | static inline float quat_inner_product(quat a, quat b) { 415 | float p = 0.f; 416 | int i; 417 | for (i = 0; i < 4; ++i) p += b[i] * a[i]; 418 | return p; 419 | } 420 | static inline void quat_conj(quat r, quat q) { 421 | int i; 422 | for (i = 0; i < 3; ++i) r[i] = -q[i]; 423 | r[3] = q[3]; 424 | } 425 | #define quat_norm vec4_norm 426 | static inline void quat_mul_vec3(vec3 r, quat q, vec3 v) { 427 | quat v_ = {v[0], v[1], v[2], 0.f}; 428 | 429 | quat_conj(r, q); 430 | quat_norm(r, r); 431 | quat_mul(r, v_, r); 432 | quat_mul(r, q, r); 433 | } 434 | static inline void mat4x4_from_quat(mat4x4 M, quat q) { 435 | float a = q[3]; 436 | float b = q[0]; 437 | float c = q[1]; 438 | float d = q[2]; 439 | float a2 = a * a; 440 | float b2 = b * b; 441 | float c2 = c * c; 442 | float d2 = d * d; 443 | 444 | M[0][0] = a2 + b2 - c2 - d2; 445 | M[0][1] = 2.f * (b * c + a * d); 446 | M[0][2] = 2.f * (b * d - a * c); 447 | M[0][3] = 0.f; 448 | 449 | M[1][0] = 2 * (b * c - a * d); 450 | M[1][1] = a2 - b2 + c2 - d2; 451 | M[1][2] = 2.f * (c * d + a * b); 452 | M[1][3] = 0.f; 453 | 454 | M[2][0] = 2.f * (b * d + a * c); 455 | M[2][1] = 2.f * (c * d - a * b); 456 | M[2][2] = a2 - b2 - c2 + d2; 457 | M[2][3] = 0.f; 458 | 459 | M[3][0] = M[3][1] = M[3][2] = 0.f; 460 | M[3][3] = 1.f; 461 | } 462 | 463 | static inline void mat4x4o_mul_quat(mat4x4 R, mat4x4 M, quat q) { 464 | /* XXX: The way this is written only works for othogonal matrices. */ 465 | /* TODO: Take care of non-orthogonal case. */ 466 | quat_mul_vec3(R[0], q, M[0]); 467 | quat_mul_vec3(R[1], q, M[1]); 468 | quat_mul_vec3(R[2], q, M[2]); 469 | 470 | R[3][0] = R[3][1] = R[3][2] = 0.f; 471 | R[3][3] = 1.f; 472 | } 473 | static inline void quat_from_mat4x4(quat q, mat4x4 M) { 474 | float r = 0.f; 475 | int i; 476 | 477 | int perm[] = {0, 1, 2, 0, 1}; 478 | int *p = perm; 479 | 480 | for (i = 0; i < 3; i++) { 481 | float m = M[i][i]; 482 | if (m < r) continue; 483 | m = r; 484 | p = &perm[i]; 485 | } 486 | 487 | r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]]); 488 | 489 | if (r < 1e-6) { 490 | q[0] = 1.f; 491 | q[1] = q[2] = q[3] = 0.f; 492 | return; 493 | } 494 | 495 | q[0] = r / 2.f; 496 | q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]]) / (2.f * r); 497 | q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]]) / (2.f * r); 498 | q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]]) / (2.f * r); 499 | } 500 | 501 | #endif 502 | -------------------------------------------------------------------------------- /VkHelloNsightAftermath/object_type_string_helper.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * 3 | * Copyright (c) 2018 The Khronos Group Inc. 4 | * Copyright (c) 2018 Valve Corporation 5 | * Copyright (c) 2018 LunarG, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * Author: Mark Lobodzinski 20 | * 21 | ****************************************************************************/ 22 | 23 | 24 | #pragma once 25 | #ifdef _WIN32 26 | #pragma warning( disable : 4065 ) 27 | #endif 28 | 29 | #include 30 | 31 | static inline const char* string_VkObjectType(VkObjectType input_value) 32 | { 33 | switch ((VkObjectType)input_value) 34 | { 35 | case VK_OBJECT_TYPE_QUERY_POOL: 36 | return "VK_OBJECT_TYPE_QUERY_POOL"; 37 | case VK_OBJECT_TYPE_OBJECT_TABLE_NVX: 38 | return "VK_OBJECT_TYPE_OBJECT_TABLE_NVX"; 39 | case VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION: 40 | return "VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION"; 41 | case VK_OBJECT_TYPE_SEMAPHORE: 42 | return "VK_OBJECT_TYPE_SEMAPHORE"; 43 | case VK_OBJECT_TYPE_SHADER_MODULE: 44 | return "VK_OBJECT_TYPE_SHADER_MODULE"; 45 | case VK_OBJECT_TYPE_SWAPCHAIN_KHR: 46 | return "VK_OBJECT_TYPE_SWAPCHAIN_KHR"; 47 | case VK_OBJECT_TYPE_SAMPLER: 48 | return "VK_OBJECT_TYPE_SAMPLER"; 49 | case VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX: 50 | return "VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX"; 51 | case VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT: 52 | return "VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT"; 53 | case VK_OBJECT_TYPE_IMAGE: 54 | return "VK_OBJECT_TYPE_IMAGE"; 55 | case VK_OBJECT_TYPE_UNKNOWN: 56 | return "VK_OBJECT_TYPE_UNKNOWN"; 57 | case VK_OBJECT_TYPE_DESCRIPTOR_POOL: 58 | return "VK_OBJECT_TYPE_DESCRIPTOR_POOL"; 59 | case VK_OBJECT_TYPE_COMMAND_BUFFER: 60 | return "VK_OBJECT_TYPE_COMMAND_BUFFER"; 61 | case VK_OBJECT_TYPE_BUFFER: 62 | return "VK_OBJECT_TYPE_BUFFER"; 63 | case VK_OBJECT_TYPE_SURFACE_KHR: 64 | return "VK_OBJECT_TYPE_SURFACE_KHR"; 65 | case VK_OBJECT_TYPE_INSTANCE: 66 | return "VK_OBJECT_TYPE_INSTANCE"; 67 | case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT: 68 | return "VK_OBJECT_TYPE_VALIDATION_CACHE_EXT"; 69 | case VK_OBJECT_TYPE_IMAGE_VIEW: 70 | return "VK_OBJECT_TYPE_IMAGE_VIEW"; 71 | case VK_OBJECT_TYPE_DESCRIPTOR_SET: 72 | return "VK_OBJECT_TYPE_DESCRIPTOR_SET"; 73 | case VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT: 74 | return "VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT"; 75 | case VK_OBJECT_TYPE_COMMAND_POOL: 76 | return "VK_OBJECT_TYPE_COMMAND_POOL"; 77 | case VK_OBJECT_TYPE_PHYSICAL_DEVICE: 78 | return "VK_OBJECT_TYPE_PHYSICAL_DEVICE"; 79 | case VK_OBJECT_TYPE_DISPLAY_KHR: 80 | return "VK_OBJECT_TYPE_DISPLAY_KHR"; 81 | case VK_OBJECT_TYPE_BUFFER_VIEW: 82 | return "VK_OBJECT_TYPE_BUFFER_VIEW"; 83 | case VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT: 84 | return "VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT"; 85 | case VK_OBJECT_TYPE_FRAMEBUFFER: 86 | return "VK_OBJECT_TYPE_FRAMEBUFFER"; 87 | case VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE: 88 | return "VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE"; 89 | case VK_OBJECT_TYPE_PIPELINE_CACHE: 90 | return "VK_OBJECT_TYPE_PIPELINE_CACHE"; 91 | case VK_OBJECT_TYPE_PIPELINE_LAYOUT: 92 | return "VK_OBJECT_TYPE_PIPELINE_LAYOUT"; 93 | case VK_OBJECT_TYPE_DEVICE_MEMORY: 94 | return "VK_OBJECT_TYPE_DEVICE_MEMORY"; 95 | case VK_OBJECT_TYPE_FENCE: 96 | return "VK_OBJECT_TYPE_FENCE"; 97 | case VK_OBJECT_TYPE_QUEUE: 98 | return "VK_OBJECT_TYPE_QUEUE"; 99 | case VK_OBJECT_TYPE_DEVICE: 100 | return "VK_OBJECT_TYPE_DEVICE"; 101 | case VK_OBJECT_TYPE_RENDER_PASS: 102 | return "VK_OBJECT_TYPE_RENDER_PASS"; 103 | case VK_OBJECT_TYPE_DISPLAY_MODE_KHR: 104 | return "VK_OBJECT_TYPE_DISPLAY_MODE_KHR"; 105 | case VK_OBJECT_TYPE_EVENT: 106 | return "VK_OBJECT_TYPE_EVENT"; 107 | case VK_OBJECT_TYPE_PIPELINE: 108 | return "VK_OBJECT_TYPE_PIPELINE"; 109 | default: 110 | return "Unhandled VkObjectType"; 111 | } 112 | } 113 | --------------------------------------------------------------------------------