diff --git a/CMakeLists.txt b/CMakeLists.txt index 30f5519..7eefa8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw) set(JSON_ROOT ${EXTERNAL_ROOT}/json) set(STB_ROOT ${EXTERNAL_ROOT}/stb) set(SPIRV_ROOT ${EXTERNAL_ROOT}/SPIRV-Cross) +set(NSAM_ROOT ${EXTERNAL_ROOT}/aftermath) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/) @@ -50,6 +51,7 @@ find_package(GLFW REQUIRED) find_package(GLM REQUIRED) find_package(STB REQUIRED) find_package(SLANG REQUIRED) +find_package(Aftermath REQUIRED) include_directories(${GLM_INCLUDE_DIRS}) include_directories(${STB_INCLUDE_DIRS}) @@ -60,6 +62,7 @@ include_directories(${GLFW_INCLUDE_DIRS}) include_directories(${SLANG_INCLUDE_DIRS}) include_directories(${ASSIMP_INCLUDE_DIRS}) include_directories(${JSON_INCLUDE_DIRS}) +include_directories(${NSAM_INCLUDE_DIRS}) include_directories(${ENGINE_ROOT}) include_directories(src/Engine) add_definitions(${Vulkan_DEFINITIONS}) @@ -78,6 +81,7 @@ target_link_libraries(SeeleEngine ${GLFW_LIBRARIES}) target_link_libraries(SeeleEngine ${SLANG_LIBRARIES}) target_link_libraries(SeeleEngine ${ASSIMP_LIBRARIES}) target_link_libraries(SeeleEngine ${JSON_LIBRARY}) +target_link_libraries(SeeleEngine ${NSAM_LIBRARIES}) #target_link_libraries(SeeleEngine ${SPIRV_LIBRARIES}) target_precompile_headers(SeeleEngine @@ -112,8 +116,9 @@ add_subdirectory(test/) add_custom_target(copy-runtime-files ALL COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res $ - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_BINARY} $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_BINARIES} $ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_GLSLANG} $ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GLFW_BINARY} $ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ASSIMP_BINARY} $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NSAM_BINARIES} $ DEPENDS SeeleEngine) \ No newline at end of file diff --git a/cmake/FindAftermath.cmake b/cmake/FindAftermath.cmake new file mode 100644 index 0000000..a0c5119 --- /dev/null +++ b/cmake/FindAftermath.cmake @@ -0,0 +1,114 @@ +# +# Find Nsight Aftermath +# +# Try to find Nvidia Nsight aftermath library. +# This module defines the following variables: +# - NSAM_INCLUDE_DIRS +# - NSAM_LIBRARIES +# - NSAM_FOUND +# +# The following variables can be set as arguments for the module. +# - NSAM_ROOT : Root library directory of NSAM +# - NSAM_USE_STATIC_LIBS : Specifies to use static version of NSAM library (Windows only) +# +# References: +# - https://github.com/progschj/OpenGL-Examples/blob/master/cmake_modules/FindNSAM.cmake +# - https://bitbucket.org/Ident8/cegui-mk2-opengl3-renderer/src/befd47200265/cmake/FindNSAM.cmake +# + +# Additional modules +include(FindPackageHandleStandardArgs) + +if (WIN32) + # Find include files + find_path( + NSAM_INCLUDE_DIR + NAMES GFSDK_Aftermath.h + PATHS + $ENV{PROGRAMFILES}/include + ${NSAM_ROOT}/include + DOC "The directory where GFSDK_Aftermath.h resides") + + + # Find library files + find_library( + NSAM_LIBRARY + NAMES GFSDK_Aftermath_Lib.${CMAKE_PLATFORM}.lib + PATHS + $ENV{PROGRAMFILES}/lib + ${NSAM_ROOT}/lib/${CMAKE_PLATFORM} + ${NSAM_ROOT}/lib + PATH_SUFFIXES x86 x64) + + find_file( + NSAM_BINARY + NAMES GFSDK_Aftermath_Lib.${CMAKE_PLATFORM}.dll + PATHS + $ENV{PROGRAMFILES}/bin + ${NSAM_ROOT}/lib/${CMAKE_PLATFORM} + ${NSAM_ROOT}/lib + PATH_SUFFIXES x86 x64) + + find_file( + NSAM_LLVM + NAMES llvm_7_0_1.dll + PATHS + $ENV{PROGRAMFILES}/bin + ${NSAM_ROOT}/lib/${CMAKE_PLATFORM} + ${NSAM_ROOT}/lib + PATH_SUFFIXES x86 x64) + +else() + # Find include files + find_path( + NSAM_INCLUDE_DIR + NAMES NSAM/nsam3.h + PATHS + /usr/include + /usr/local/include + /sw/include + /opt/local/include + DOC "The directory where GL/nsam.h resides") + + # Find library files + # Try to use static libraries + #find_library( + # NSAM_LIBRARY + # NAMES nsam3 + # PATHS + # /usr/lib64 + # /usr/lib + # /usr/local/lib64 + # /usr/local/lib + # /sw/lib + # /opt/local/lib + # ${NSAM_ROOT}/lib + # DOC "The NSAM library") + set(NSAM_LIBRARY "") + + find_file( + NSAM_BINARY + NAMES libnsam${CMAKE_DEBUG_POSTFIX}.so + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib64 + /usr/local/lib + /sw/lib + /opt/local/lib + ${NSAM_ROOT}/src + ) +endif() + +# Handle REQUIRD argument, define *_FOUND variable +find_package_handle_standard_args(NSAM DEFAULT_MSG NSAM_INCLUDE_DIR NSAM_BINARY) + +# Define NSAM_LIBRARIES and NSAM_INCLUDE_DIRS +if (NSAM_FOUND) + set(NSAM_LIBRARIES ${NSAM_LIBRARY}) + set(NSAM_INCLUDE_DIRS ${NSAM_INCLUDE_DIR}) + set(NSAM_BINARIES ${NSAM_BINARY} ${NSAM_LLVM}) +endif() + +# Hide some variables +mark_as_advanced(NSAM_INCLUDE_DIR NSAM_LIBRARY) \ No newline at end of file diff --git a/external/aftermath/LICENSE b/external/aftermath/LICENSE new file mode 100644 index 0000000..8b73387 --- /dev/null +++ b/external/aftermath/LICENSE @@ -0,0 +1,601 @@ +Copyright (c) 2017-2020, NVIDIA CORPORATION. All rights reserved. + +NVIDIA CORPORATION and its licensors retain all intellectual property and proprietary +rights in and to this software, related documentation and any modifications thereto. Any +use, reproduction, disclosure or distribution of this software and related documentation +without an express license agreement from NVIDIA CORPORATION is strictly prohibited. + +LICENSE AGREEMENT FOR NVIDIA SOFTWARE DEVELOPMENT KITS + +This license agreement, including exhibits attached ("Agreement") is a legal agreement +between you and NVIDIA Corporation ("NVIDIA") and governs your use of a NVIDIA software +development kit ("SDK"). + +Each SDK has its own set of software and materials, but here is a description of the types +of items that may be included in a SDK: source code, header files, APIs, data sets and +assets (examples include images, textures, models, scenes, videos, native API input/output +files), binary software, sample code, libraries, utility programs, programming code and +documentation. + +This Agreement can be accepted only by an adult of legal age of majority in the country in +which the SDK is used. + +If you are entering into this Agreement on behalf of a company or other legal entity, you +represent that you have the legal authority to bind the entity to this Agreement, in which +case "you" will mean the entity you represent. + +If you don’t have the required age or authority to accept this Agreement, or if you don’t +accept all the terms and conditions of this Agreement, do not download, install or use the +SDK. + +You agree to use the SDK only for purposes that are permitted by (a) this Agreement, and +(b) any applicable law, regulation or generally accepted practices or guidelines in the +relevant jurisdictions. + +1. License. + +1.1 Grant + +Subject to the terms of this Agreement, NVIDIA hereby grants you a non-exclusive, +non-transferable license, without the right to sublicense (except as expressly provided in +this Agreement) to: + +(i) Install and use the SDK, and + +(ii) Distribute those portions of the SDK that are identified in this Agreement as +distributable, as incorporated in object code format into a software application that +meets the distribution requirements indicated in this Agreement. + +1.2 Distribution Requirements + +These are the distribution requirements for you to exercise the distribution grant: + +(i) Your application must have material additional functionality, beyond the included +portions of the SDK. + +(ii) The distributable portions of the SDK shall only be accessed by your application. + +(iii) The following notice shall be included in modifications and derivative works of +sample source code distributed: "This software contains source code provided by NVIDIA +Corporation." + +(iv) Unless a developer tool is identified in this Agreement as distributable, it is +delivered for your internal use only. + +(v) The terms under which you distribute your application must be consistent with the +terms of this Agreement, including (without limitation) terms relating to the license +grant and license restrictions and protection of NVIDIA’s intellectual property rights. +Additionally, you agree that you will protect the privacy, security and legal rights of +your application users. + +(vi) You agree to notify NVIDIA in writing of any known or suspected distribution or use +of the SDK not in compliance with the requirements of this Agreement, and to enforce the +terms of your agreements with respect to distributed SDK. + +1.3 Authorized Users + +You may allow employees and contractors of your entity or of your subsidiary(ies) to +access and use the SDK from your secure network to perform work on your behalf. + +If you are an academic institution you may allow users enrolled or employed by the +academic institution to access and use the SDK from your secure network. + +You are responsible for the compliance with the terms of this Agreement by your authorized +users. If you become aware that your authorized users didn’t follow the terms of this +Agreement, you agree to take reasonable steps to resolve the non-compliance and prevent +new occurrences. + +1.4 Pre-Release SDK + +The SDK versions identified as alpha, beta, preview or otherwise as pre-release, may not +be fully functional, may contain errors or design flaws, and may have reduced or different +security, privacy, accessibility, availability, and reliability standards relative to +commercial versions of NVIDIA software and materials. Use of a pre-release SDK may result +in unexpected results, loss of data, project delays or other unpredictable damage or loss. +You may use a pre-release SDK at your own risk, understanding that pre-release SDKs are +not intended for use in production or business-critical systems. NVIDIA may choose not to +make available a commercial version of any pre-release SDK. NVIDIA may also choose to +abandon development and terminate the availability of a pre-release SDK at any time +without liability. + +1.5 Updates + +NVIDIA may, at its option, make available patches, workarounds or other updates to this +SDK. Unless the updates are provided with their separate governing terms, they are deemed +part of the SDK licensed to you as provided in this Agreement. + +You agree that the form and content of the SDK that NVIDIA provides may change without +prior notice to you. While NVIDIA generally maintains compatibility between versions, +NVIDIA may in some cases make changes that introduce incompatibilities in future versions +of the SDK. + +1.6 Third Party Licenses + +The SDK may come bundled with, or otherwise include or be distributed with, third party +software licensed by a NVIDIA supplier and/or open source software provided under an open +source license. Use of third-party software is subject to the third-party license terms, +or in the absence of third party terms, the terms of this Agreement. Copyright to +third-party software is held by the copyright holders indicated in the third-party +software or license. + +1.7 Reservation of Rights + +NVIDIA reserves all rights, title and interest in and to the SDK not expressly granted to +you under this Agreement. + +2. Limitations. + +The following license limitations apply to your use of the SDK: + +2.1 You may not reverse engineer, decompile or disassemble, or remove copyright or other +proprietary notices from any portion of the SDK or copies of the SDK. + +2.2 Except as expressly provided in this Agreement, you may not copy, sell, rent, +sublicense, transfer, distribute, modify, or create derivative works of any portion of the +SDK. + +2.3 Unless you have an agreement with NVIDIA for this purpose, you may not indicate that +an application created with the SDK is sponsored or endorsed by NVIDIA. + +2.4 You may not bypass, disable, or circumvent any encryption, security, digital rights +management or authentication mechanism in the SDK. + +2.5 You may not use the SDK in any manner that would cause it to become subject to an open +source software license. As examples, licenses that require as a condition of use, +modification, and/or distribution that the SDK be (i) disclosed or distributed in source +code form; (ii) licensed for the purpose of making derivative works; or (iii) +redistributable at no charge. + +2.6 Unless you have an agreement with NVIDIA for this purpose, you may not use the SDK +with any system or application where the use or failure of the system or application can +reasonably be expected to threaten or result in personal injury, death, or catastrophic +loss. Examples include use in nuclear, avionics, navigation, military, medical, life +support or other life critical applications. NVIDIA does not design, test or manufacture +the SDK for these critical uses and NVIDIA shall not be liable to you or any third party, +in whole or in part, for any claims or damages arising from such uses. + +2.7 You agree to defend, indemnify and hold harmless NVIDIA and its affiliates, and their +respective employees, contractors, agents, officers and directors, from and against any +and all claims, damages, obligations, losses, liabilities, costs or debt, fines, +restitutions and expenses (including but not limited to attorney’s fees and costs incident +to establishing the right of indemnification) arising out of or related to your use of the +SDK outside of the scope of this Agreement, or not in compliance with its terms. + +3. Ownership. + +3.1 NVIDIA or its licensors hold all rights, title and interest in and to the SDK and its +modifications and derivative works, including their respective intellectual property +rights. This SDK may include software and materials from NVIDIA’s licensors, and these +licensors are intended third party beneficiaries that may enforce this Agreement with +respect to their intellectual property rights. + +3.2 You may, but don’t have to, provide to NVIDIA suggestions, feature requests or other +feedback regarding the SDK, including possible enhancements or modifications to the SDK. +For any feedback that you voluntarily provide, you hereby grant NVIDIA and its affiliates +a perpetual, non-exclusive, worldwide, irrevocable license to use, reproduce, modify, +license, sublicense (through multiple tiers of sublicensees), and distribute (through +multiple tiers of distributors) it without the payment of any royalties or fees to you. +NVIDIA will use feedback at its choice. NVIDIA is constantly looking for ways to improve +its products, so you may send feedback to NVIDIA through the developer portal at +https://developer.nvidia.com. + +4. No Warranties. + +THE SDK IS PROVIDED BY NVIDIA "AS IS" AND "WITH ALL FAULTS." TO THE MAXIMUM EXTENT +PERMITTED BY LAW, NVIDIA AND ITS AFFILIATES EXPRESSLY DISCLAIM ALL WARRANTIES OF ANY KIND +OR NATURE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, +OR THE ABSENCE OF ANY DEFECTS THEREIN, WHETHER LATENT OR PATENT. NO WARRANTY IS MADE ON +THE BASIS OF TRADE USAGE, COURSE OF DEALING OR COURSE OF TRADE. + +5. Limitations of Liability. + +TO THE MAXIMUM EXTENT PERMITTED BY LAW, NVIDIA AND ITS AFFILIATES SHALL NOT BE LIABLE FOR +ANY SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL DAMAGES, OR ANY LOST PROFITS, LOSS OF +USE, LOSS OF DATA OR LOSS OF GOODWILL, OR THE COSTS OF PROCURING SUBSTITUTE PRODUCTS, +ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT OR THE USE OR PERFORMANCE OF THE SDK, +WHETHER SUCH LIABILITY ARISES FROM ANY CLAIM BASED UPON BREACH OF CONTRACT, BREACH OF +WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCT LIABILITY OR ANY OTHER CAUSE OF ACTION OR +THEORY OF LIABILITY. IN NO EVENT WILL NVIDIA’S AND ITS AFFILIATES TOTAL CUMULATIVE +LIABILITY UNDER OR ARISING OUT OF THIS AGREEMENT EXCEED US$10.00. THE NATURE OF THE +LIABILITY OR THE NUMBER OF CLAIMS OR SUITS SHALL NOT ENLARGE OR EXTEND THIS LIMIT. + +These exclusions and limitations of liability shall apply regardless if NVIDIA or its +affiliates have been advised of the possibility of such damages, and regardless of whether +a remedy fails its essential purpose. These exclusions and limitations of liability form +an essential basis of the bargain between the parties, and, absent any of these exclusions +or limitations of liability, the provisions of this Agreement, including, without +limitation, the economic terms, would be substantially different. + +6. Termination. + +6.1 This Agreement will continue to apply until terminated by either you or NVIDIA as +described below. + +6.2 If you want to terminate this Agreement, you may do so by stopping to use the SDK. + +6.3 NVIDIA may, at any time, terminate this Agreement if: (i) you fail to comply with any +term of this Agreement and the non-compliance is not fixed within thirty (30) days +following notice from NVIDIA (or immediately if you violate NVIDIA’s intellectual property +rights); (ii) you commence or participate in any legal proceeding against NVIDIA with +respect to the SDK; or (iii) NVIDIA decides to no longer provide the SDK in a country or, +in NVIDIA’s sole discretion, the continued use of it is no longer commercially viable. + +6.4 Upon any termination of this Agreement, you agree to promptly discontinue use of the +SDK and destroy all copies in your possession or control. Your prior distributions in +accordance with this Agreement are not affected by the termination of this Agreement. Upon +written request, you will certify in writing that you have complied with your commitments +under this section. Upon any termination of this Agreement all provisions survive except +for the licenses granted to you. + +7. General. + +If you wish to assign this Agreement or your rights and obligations, including by merger, +consolidation, dissolution or operation of law, contact NVIDIA to ask for permission. Any +attempted assignment not approved by NVIDIA in writing shall be void and of no effect. +NVIDIA may assign, delegate or transfer this Agreement and its rights and obligations, and +if to a non-affiliate you will be notified. + +You agree to cooperate with NVIDIA and provide reasonably requested information to verify +your compliance with this Agreement. + +This Agreement will be governed in all respects by the laws of the United States and of +the State of Delaware as those laws are applied to contracts entered into and performed +entirely within Delaware by Delaware residents, without regard to the conflicts of laws +principles. The United Nations Convention on Contracts for the International Sale of Goods +is specifically disclaimed. You agree to all terms of this Agreement in the English +language. + +The state or federal courts residing in Santa Clara County, California shall have +exclusive jurisdiction over any dispute or claim arising out of this Agreement. +Notwithstanding this, you agree that NVIDIA shall still be allowed to apply for injunctive +remedies or an equivalent type of urgent legal relief in any jurisdiction. + +If any court of competent jurisdiction determines that any provision of this Agreement is +illegal, invalid or unenforceable, such provision will be construed as limited to the +extent necessary to be consistent with and fully enforceable under the law and the +remaining provisions will remain in full force and effect. Unless otherwise specified, +remedies are cumulative. + +Each party acknowledges and agrees that the other is an independent contractor in the +performance of this Agreement. + +The SDK has been developed entirely at private expense and is "commercial items" +consisting of "commercial computer software" and "commercial computer software +documentation" provided with RESTRICTED RIGHTS. Use, duplication or disclosure by the U.S. +Government or a U.S. Government subcontractor is subject to the restrictions in this +Agreement pursuant to DFARS 227.7202-3(a) or as set forth in subparagraphs (b)(1) and (2) +of the Commercial Computer Software - Restricted Rights clause at FAR 52.227-19, as +applicable. Contractor/manufacturer is NVIDIA, 2788 San Tomas Expressway, Santa Clara, CA +95051. + +The SDK is subject to United States export laws and regulations. You agree that you will +not ship, transfer or export the SDK into any country, or use the SDK in any manner, +prohibited by the United States Bureau of Industry and Security or economic sanctions +regulations administered by the U.S. Department of Treasury’s Office of Foreign Assets +Control (OFAC), or any applicable export laws, restrictions or regulations. These laws +include restrictions on destinations, end users and end use. By accepting this Agreement, +you confirm that you are not a resident or citizen of any country currently embargoed by +the U.S. and that you are not otherwise prohibited from receiving the SDK. + +Any notice delivered by NVIDIA to you under this Agreement will be delivered via mail, +email or fax. You agree that any notices that NVIDIA sends you electronically will satisfy +any legal communication requirements. Please direct your legal notices or other +correspondence to NVIDIA Corporation, 2788 San Tomas Expressway, Santa Clara, California +95051, United States of America, Attention: Legal Department. + +This Agreement and any exhibits incorporated into this Agreement constitute the entire +agreement of the parties with respect to the subject matter of this Agreement and +supersede all prior negotiations or documentation exchanged between the parties relating +to this SDK license. Any additional and/or conflicting terms on documents issued by you +are null, void, and invalid. Any amendment or waiver under this Agreement shall be in +writing and signed by representatives of both parties. + +(v. July 22, 2019) + +NSIGHT AFTERMATH SUPPLEMENT TO SOFTWARE LICENSE AGREEMENT FOR NVIDIA SOFTWARE DEVELOPMENT +KITS + +The terms in this supplement govern your use of the NVIDIA Nsight Aftermath SDK under the +terms of your license agreement ("Agreement") as modified by this supplement. Capitalized +terms used but not defined below have the meaning assigned to them in the Agreement. + +This supplement is an exhibit to the Agreement and is incorporated as an integral part of +the Agreement. In the event of conflict between the terms in this supplement and the terms +in the Agreement, the terms in this supplement govern. + +1. Distribution. + +The following portions of the SDK are distributable under the Agreement: the .dll / .so files. + +2. Usage. + +Please read the accompanying usage guidelines document (nsight-aftermath-usage-guidelines.txt) +for information on how Nsight Aftermath is intended to be used. + +(v. October 30, 2019) + + +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ + +The Nsight Aftermath SDK makes use of third-party libraries. The licensee's use of the +SDK is subject to the following additional terms and conditions: + +JSON for Modern C++ (https://nlohmann.github.io/json/) + + The class is licensed under the MIT License: + + Copyright (c) 2013-2019 Niels Lohmann + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, + merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be included in all copies + or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the + MIT License (see above). Copyright (c) 2008-2009 Björn Hoehrmann bjoern@hoehrmann.de + + The class contains a slightly modified version of the Grisu2 algorithm from Florian + Loitsch which is licensed under the MIT License (see above). Copyright (c) 2009 + Florian Loitsch + + +FlatBuffers: Memory Efficient Serialization Library (http://google.github.io/flatbuffers/) + + Apache License Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and distribution + as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner + that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other entities that + control, are controlled by, or are under common control with that entity. For the + purposes of this definition, "control" means (i) the power, direct or indirect, to + cause the direction or management of such entity, whether by contract or otherwise, or + (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) + beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions + granted by this License. + + "Source" form shall mean the preferred form for making modifications, including but + not limited to software source code, documentation source, and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation or + translation of a Source form, including but not limited to compiled object code, + generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, made + available under the License, as indicated by a copyright notice that is included in or + attached to the work (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, that is + based on (or derived from) the Work and for which the editorial revisions, + annotations, elaborations, or other modifications represent, as a whole, an original + work of authorship. For the purposes of this License, Derivative Works shall not + include works that remain separable from, or merely link (or bind by name) to the + interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original version of + the Work and any modifications or additions to that Work or Derivative Works thereof, + that is intentionally submitted to Licensor for inclusion in the Work by the copyright + owner or by an individual or Legal Entity authorized to submit on behalf of the + copyright owner. For the purposes of this definition, "submitted" means any form of + electronic, verbal, or written communication sent to the Licensor or its + representatives, including but not limited to communication on electronic mailing + lists, source code control systems, and issue tracking systems that are managed by, or + on behalf of, the Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise designated in + writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom + a Contribution has been received by Licensor and subsequently incorporated within the + Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of this License, + each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, + no-charge, royalty-free, irrevocable copyright license to reproduce, prepare + Derivative Works of, publicly display, publicly perform, sublicense, and distribute + the Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of this License, each + Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, + royalty-free, irrevocable (except as stated in this section) patent license to make, + have made, use, offer to sell, sell, import, and otherwise transfer the Work, where + such license applies only to those patent claims licensable by such Contributor that + are necessarily infringed by their Contribution(s) alone or by combination of their + Contribution(s) with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a cross-claim or + counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated + within the Work constitutes direct or contributory patent infringement, then any + patent licenses granted to You under this License for that Work shall terminate as of + the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative + Works thereof in any medium, with or without modifications, and in Source or Object + form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this + License; and + + (b) You must cause any modified files to carry prominent notices stating that You + changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, + all copyright, patent, trademark, and attribution notices from the Source form of the + Work, excluding those notices that do not pertain to any part of the Derivative Works; + and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any + Derivative Works that You distribute must include a readable copy of the attribution + notices contained within such NOTICE file, excluding those notices that do not pertain + to any part of the Derivative Works, in at least one of the following places: within a + NOTICE text file distributed as part of the Derivative Works; within the Source form + or documentation, if provided along with the Derivative Works; or, within a display + generated by the Derivative Works, if and wherever such third-party notices normally + appear. The contents of the NOTICE file are for informational purposes only and do not + modify the License. You may add Your own attribution notices within Derivative Works + that You distribute, alongside or as an addendum to the NOTICE text from the Work, + provided that such additional attribution notices cannot be construed as modifying the + License. + + You may add Your own copyright statement to Your modifications and may provide + additional or different license terms and conditions for use, reproduction, or + distribution of Your modifications, or for any such Derivative Works as a whole, + provided Your use, reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, any + Contribution intentionally submitted for inclusion in the Work by You to the Licensor + shall be under the terms and conditions of this License, without any additional terms + or conditions. Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed with Licensor + regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade names, + trademarks, service marks, or product names of the Licensor, except as required for + reasonable and customary use in describing the origin of the Work and reproducing the + content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, + Licensor provides the Work (and each Contributor provides its Contributions) on an "AS + IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, + including, without limitation, any warranties or conditions of TITLE, + NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely + responsible for determining the appropriateness of using or redistributing the Work + and assume any risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, whether in tort + (including negligence), contract, or otherwise, unless required by applicable law + (such as deliberate and grossly negligent acts) or agreed to in writing, shall any + Contributor be liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a result of this + License or out of the use or inability to use the Work (including but not limited to + damages for loss of goodwill, work stoppage, computer failure or malfunction, or any + and all other commercial damages or losses), even if such Contributor has been advised + of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing the Work or + Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of + support, warranty, indemnity, or other liability obligations and/or rights consistent + with this License. However, in accepting such obligations, You may act only on Your + own behalf and on Your sole responsibility, not on behalf of any other Contributor, + and only if You agree to indemnify, defend, and hold each Contributor harmless for any + liability incurred by, or claims asserted against, such Contributor by reason of your + accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following boilerplate notice, + with the fields enclosed by brackets "[]" replaced with your own identifying + information. (Don't include the brackets!) The text should be enclosed in the + appropriate comment syntax for the file format. We also recommend that a file or class + name and description of purpose be included on the same "printed page" as the + copyright notice for easier identification within third-party archives. + + Copyright 2014 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this + file except in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under + the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + ANY KIND, either express or implied. See the License for the specific language + governing permissions and limitations under the License. + + +The LLVM Compiler Infrastructure (http://llvm.org/) + + ============================================================================== + LLVM Release License + ============================================================================== + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2018 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. + + ============================================================================== + Copyrights and Licenses for Third Party Software Distributed with LLVM: + ============================================================================== + The LLVM software contains code written by third parties. Such software will + have its own individual LICENSE.TXT file in the directory in which it appears. + This file will describe the copyrights, license, and restrictions which apply + to that code. + + The disclaimer of warranty in the University of Illinois Open Source License + applies to all code in the LLVM Distribution, and nothing in any of the + other licenses gives permission to use the names of the LLVM Team or the + University of Illinois to endorse or promote products derived from this + Software. + + The following pieces of software have additional or alternate copyrights, + licenses, and/or restrictions: + + Program Directory + ------- --------- + Google Test llvm/utils/unittest/googletest + OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex} + pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT} + ARM contributions llvm/lib/Target/ARM/LICENSE.TXT + md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h + diff --git a/external/aftermath/Readme.md b/external/aftermath/Readme.md new file mode 100644 index 0000000..f86bd26 --- /dev/null +++ b/external/aftermath/Readme.md @@ -0,0 +1,889 @@ +# Nsight Aftermath SDK + +Aftermath is a compact, easy to use C/C++ library aimed at developers of D3D12 +or Vulkan based applications on Microsoft Windows or Linux, enabling post-mortem +GPU crash analysis on NVIDIA GeForce based GPUs. + +## Key Features + +The Nsight Aftermath SDK is an easy to use C/C++ API (shared libraries + header +files), which provides support for three major use cases: + +* GPU crash dump creation +* GPU crash dump analysis +* Application instrumentation with light-weight GPU event markers + +Nsight Aftermath's GPU crash dump collection performance footprint is low +enough to include in a shipping application - allowing developers to mine +details on why the GPU crashed in the wild, and gather GPU crash dumps for +further analysis (should the required cloud infrastructure already exist). + +## Application Instrumentation with Event Markers + +In its basic form, this works by allowing programmers to insert markers into +the GPU pipeline, which can be read post-TDR, in order to determine what work +item the GPU was processing at the point of failure. Nsight Aftermath also +includes a facility to query the current device state, much like the +conventional graphics APIs, but reporting a finer grained reason. + +One of the key principles of Aftermath is for the marker insertion to be as +unobtrusive as possible. Avoiding situations common with other similar +debuggers, where their associated performance cost changes timing enough to +make a bug repro vanish: a "Heisenbug". Aftermath avoids this problem by +design, while simultaneously not compromising on functionality: a catch-all +solution for post-mortem GPU crash analysis. + +For Vulkan the Aftermath event marker functionality is exposed as a Vulkan +extension: `NV_device_diagnostic_checkpoints`. + +## GPU Crash Dump Creation + +In addition to event marker-based GPU work tracking and device state queries, +Nsight Aftermath also supports the creation of GPU crash dumps for in-depth +post-mortem GPU crash analysis. + +Integrating GPU crash dump creation into a graphics application allows +collecting and processing the GPU crash dumps by already established crash +handling workflows and infrastructure. + +## GPU Crash Dump Inspection and Analysis + +There are two possibilities for a developer to inspect and analyze GPU crash +dumps collected from an application enabled with Nsight Aftermath's GPU crash +dump creation feature: + +* Load the GPU crash dump into Nsight Graphics and use the graphical GPU crash + dump inspector. This option allows for quick and easy access to the data + stored in the GPU crash dump for visual inspection. +* Use the Nsight Aftermath GPU crash dump decoding functions to + programmatically access the data stored in the GPU crash dump. This allows + for automatic processing and binning of GPU crash dumps in a user-defined + fashion. + +## Distribution + +The following portions of the SDK are distributable: all .dll / .so files in the +`lib` directory. + +NOTE: Redistribution of the files is subject to the terms and conditions listed +in the LICENSE file, including the terms and conditions inherited from any +third-party component used within this product. + +## Support + +* Microsoft Windows 10 (Version 1809, Version 1903, Version 1909) +* Linux (kernel 4.15.0 or newer) +* D3D12, DXR, D3D11 (basic support), Vulkan +* NVIDIA Turing GPU +* NVIDIA Display Driver R440 or newer (for D3D) +* NVIDIA Display Driver R445 or newer (for Vulkan on Windows) +* NVIDIA Display Driver R455 or newer (for Vulkan on Linux) + +# Usage Examples + +In this section some code snippets can be found that show how to use the Nsight +Aftermath API for collecting and decoding crash dumps for a D3D12 or Vulkan +application. + +The code samples cover the following commonly required tasks: + +1. Enable GPU crash dump collection in an application +2. Configure what data to include in GPU crash dumps +3. Instrument an application with Aftermath event markers +4. Handle GPU crash dump callback events +5. Disable GPU crash dump collection +6. Use the GPU crash dump decoding API + +## Enabling GPU Crash Dumps + +An application enables GPU crash dump creation by calling +`GFSDK_Aftermath_EnableGpuCrashDumps()`. To use the Nsight Aftermath API +functions related to GPU crash dump collection include the +`GFSDK_Aftermath_GpuCrashDump.h` header file. + +GPU crash dump collection should be enabled before the application creates any +D3D12, D3D11, or Vulkan device. No GPU crash dumps will be generated for GPU +crashes or hangs related to devices that were created before the +`GFSDK_Aftermath_EnableGpuCrashDumps()` call. + +Besides enabling the GPU crash dump feature, this call allows the application +to register a callback function that will be invoked once a GPU crash is +detected. In addition, the application can also provide two optional callback +functions that will be invoked if debug information for shaders is available or +the application intends to provide additional description or context for the +exception, such as the current state of the application at the time of the +crash, to be included with the GPU crash dump. + +The following code snippet shows an example of how to enable GPU crash dumps +and how to setup the callbacks for crash dump notifications, for shader debug +information notifications, and for providing additional crash dump description +data. Only the crash dump callback is mandatory. The other two callbacks are +optional and can be omitted by passing a NULL pointer if the corresponding +functionality is not needed. In this example, GPU cash dumps are only enabled +for D3D12 and D3D11 devices. For watching Vulkan devices the +`GFSDK_Aftermath_EnableGpuCrashDumps()` functions must be called with +`GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan`. It is also possible to +combine both flags, if an application uses both the D3D and the Vulkan API. + +```C++ + void MyApp::InitDevice() + { + [...] + + // Enable GPU crash dumps and register callbacks. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_EnableGpuCrashDumps( + GFSDK_Aftermath_Version_API, + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_DX, + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_Default, // Default behavior. + GpuCrashDumpCallback, // Register callback for GPU crash dumps. + ShaderDebugInfoCallback, // Register callback for shader debug information. + CrashDumpDescriptionCallback, // Register callback for GPU crash dump description. + &m_gpuCrashDumpTracker)); // Set the GpuCrashTracker object as user data passed back by the above callbacks. + + [...] + } + + // Static wrapper for the GPU crash dump handler. See the 'Handling GPU crash dump Callbacks' section for details. + void MyApp::GpuCrashDumpCallback(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize, void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnCrashDump(pGpuCrashDump, gpuCrashDumpSize); + } + + // Static wrapper for the shader debug information handler. See the 'Handling Shader Debug Information callbacks' section for details. + void MyApp::ShaderDebugInfoCallback(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize, void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize); + } + + // Static wrapper for the GPU crash dump description handler. See the 'Handling GPU Crash Dump Description Callbacks' section for details. + void MyApp::CrashDumpDescriptionCallback(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnDescription(addDescription); + } +``` + +Enabling GPU crash dumps in an application with +`GFSDK_Aftermath_EnableGpuCrashDumps()` will override any settings from an +already active Nsight Aftermath GPU crash dump monitor for this application. +That means the GPU crash dump monitor will not be notified of any GPU crash +related to this process nor will it create any GPU crash dumps or shader debug +information files for D3D or Vulkan devices that are created after the function +was called. Also, all configuration settings made in the GPU crash dump monitor +will be ignored. + +## Configuring GPU Crash Dumps + +Which data will be included in GPU crash dumps is configured by the Aftermath +per-device feature flags. How to configure Aftermath feature flags differs +between D3D and Vulkan. + +For D3D, the application must call the appropriate +`GFSDK_Aftermath_DX*_Initialize()` functions to initialize the desired Aftermath +feature flags. + +For Vulkan, Aftermath feature flags are configured at logical device creation time +via the `VK_NV_device_diagnostics_config` extension. + +The following sample code shows how to use `GFSDK_Aftermath_DX12_Initialize()` +to enable the following features for a D3D12 device: + +* _Aftermath event markers_ - this will include information about the Aftermath + event marker nearest to the crash. Using event markers should be considered + carefully. Injecting markers in high-frequency code paths can introduce hight + CPU overhead. +* _Resource tracking_ - this will include additional information about the + resource related to a GPU virtual address seen in the case of a crash due to + a GPU page fault. This includes, for example, information about the size of + the resource, its format, and the current deletion status of the resource + object. +* _Call stack capturing_ - this will include call stack and module information + for the draw call, compute dispatch, or resource copy nearest to the crash. + Using this option should be considered carefully. Enabling call stack + capturing can cause considerable CPU overhead. +* _Generating shader debug information_ - this instructs the shader compiler to + generate debug information (line tables) for all shaders. Using this option + should be considered carefully. It may cause considerable shader compilation + overhead and additional overhead for handling the corresponding shader debug + information callbacks. + +``` C++ + void MyApp::InitDevice() + { + [...] + + D3D12CreateDevice(hardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device))); + + // Initialize Nsight Aftermath for this device. + const uint32_t aftermathFlags = + GFSDK_Aftermath_FeatureFlags_EnableMarkers | // Enable event marker tracking. + GFSDK_Aftermath_FeatureFlags_EnableResourceTracking | // Enable tracking of resources. + GFSDK_Aftermath_FeatureFlags_CallStackCapturing | // Capture call stacks for all draw calls, compute dispatches, and resource copies. + GFSDK_Aftermath_FeatureFlags_GenerateShaderDebugInfo; // Generate debug information for shaders. + + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_DX12_Initialize( + GFSDK_Aftermath_Version_API, + aftermathFlags, + m_device.Get())); + + [...] + } +``` + +The same kind of Aftermath feature selection for a Vulkan device could look like +this: + +``` C++ + void MyApp::InitDevice() + { + std::vector extensionNames; + + [...] + + // Enable NV_device_diagnostic_checkpoints extension to be able to + // use Aftermath event markers. + extensionNames.push_back(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME); + + // Enable NV_device_diagnostics_config extension to configure Aftermath + // features. + extensionNames.push_back(VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME); + + // Set up device creation info for Aftermath feature flag configuration. + VkDeviceDiagnosticsConfigFlagsNV aftermathFlags = + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | // Enable tracking of resources. + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | // Capture call stacks for all draw calls, compute dispatches, and resource copies. + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV; // Generate debug information for shaders. + VkDeviceDiagnosticsConfigCreateInfoNV aftermathInfo = {}; + aftermathInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + aftermathInfo.flags = aftermathFlags; + + // Set up device creation info. + VkDeviceCreateInfo deviceInfo = {}; + deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + deviceInfo.pNext = &aftermath_info; + deviceInfo.queueCreateInfoCount = 1; + deviceInfo.pQueueCreateInfos = &queueInfo; + deviceInfo.enabledExtensionCount = extensionNames.size(); + deviceInfo.ppEnabledExtensionNames = extensionNames.data(); + + // Create the logical device. + VkDevice device; + vkCreateDevice(physicalDevice, &deviceInfo, NULL, &device); + + [...] + } +``` + +## Inserting Event Markers + +The Aftermath API provides a simple and light-weight solution for inserting +event markers on the GPU timeline. + +Here is some D3D12 example code that shows how to create the necessary command +context handle with `GFSDK_Aftermath_DX12_CreateContextHandle()` and how to +call `GFSDK_Aftermath_SetEventMarker()` to set a simple event marker with a +character string as payload. + +```C++ + void MyApp::PopulateCommandList() + { + // Create the command list. + m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator.Get(), m_pipelineState.Get(), IID_PPV_ARGS(&m_commandList))); + + // Create an Nsight Aftermath context handle for setting Aftermath event markers in this command list. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_DX12_CreateContextHandle(m_commandList.Get(), &m_hAftermathCommandListContext)); + + [...] + + // Add an Aftermath event marker with a 0-terminated string as payload. + std::string eventMarker = "Draw Triangle"; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_SetEventMarker(m_hAftermathCommandListContext, (void*)eventMarker.c_str(), (unsigned int)eventMarker.size() + 1)); + m_commandList->DrawInstanced(3, 1, 0, 0); + + [...] + } +``` + +For reduced CPU overhead, use `GFSDK_Aftermath_SetEventMarker()` with +`dataSize=0`. This instructs Aftermath not to allocate and copy off memory +internally, relying on the application to manage marker pointers itself. + +For Vulkan, similar functionality is provided via the +`NV_device_diagnostic_checkpoints` extension. When this extension is enabled for +a Vulkan device event markers can be inserted in a command buffer with the +`vkCmdSetCheckpointNV()` function. + +```C++ + void MyApp::RecordCommandBuffer() + { + [...] + + // Add an Aftermath event marker pointing to a null-terminated string. + vkCmdSetCheckpointNV(commandBuffer, "Draw Cube"); + + [...] + } +``` + +## Handling GPU Crash Dump Callbacks + +When Nsight Aftermath GPU crash dumps are enabled, and a GPU crash or hang is +detected, the necessary data is gathered and a GPU crash dump is created from +it. Then the GPU crash dump callback function that was registered with the +`GFSDK_Aftermath_EnableGpuCrashDumps()` will be invoked to notify the +application. In the callback the application can either decode the GPU crash +dump data using the GPU crash dump decoding API or forward it to the crash +handling infrastructure. + +In the simple example implementation of a GPU crash dump callback handler is +shown below the GPU crash dump data is simply stored to a file. This file could +then be opened for analysis with Nsight Graphics. + +```C++ + // Handler for GPU crash dump callbacks (called by GpuCrashDumpCallback). + void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) + { + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Write to file for later in-depth analysis. + WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); + } +``` + +Note that all callback functions are free-threaded, and that the application is +responsible for providing thread-safe callback handlers. + +It is also important to note that `DXGI_ERROR` error notification is asynchronous +to the NVIDIA display driver's GPU crash handling. That means applications +should check the return value of IDXGISwapChain::Present() and give the Nsight +Aftermath GPU crash dump processing thread some time to do its work before +releasing the D3D device or terminating the process. + +## Handling GPU Crash Dump Description Callbacks + +An application can register an optional callback function that allows it to +provide supplemental information about a crash. This callback is called after +the GPU crash happened, but before the actual GPU crash dump callback. This +presents the opportunity for the application to provide information such as +application name, application version, or user defined data, for example, +current engine state. The data provided will be stored in the GPU crash dump. + +Here is an example of a basic GPU crash dump description handler. Data is added +to the crash dump by calling the `addDescription()` function provided by the +callback. + +```C++ + // Handler for GPU crash dump description callbacks (called by CrashDumpDescriptionCallback). + void GpuCrashTracker::OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription) + { + // Add some basic description about the crash. + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "Hello Nsight Aftermath"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion, "v1.0"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined, "This is a GPU crash dump example"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 1, "Engine State: Rendering"); + } +``` + +Note that all callback functions are free-threaded; the application is +responsible for providing thread-safe callback handlers. + +## Handling Shader Debug Information Callbacks + +If the device was configured with the `GenerateShaderDebugInfo` feature flag, +the generated shader debug information will be communicated to the application +through the (optional) shader debug information callback function that was +registered when the `GFSDK_Aftermath_EnableGpuCrashDumps()` was called. This debug +information will be required to map from shader instruction addresses to +intermediate assembly language (IL) instructions or high-level source lines when +analyzing a crash dump in Nsight Graphics or when using the GPU crash dump to +JSON decoding functions of the Nsight Aftermath API. If this functionality is +not required, an application can omit the `GenerateShaderDebugInfo` flag when +configuring the device and pass `nullptr` for the shader debug information +callback. This might be desirable, because generating shader debug information +incurs overhead in shader compilation and for handling the callback. + +Here is a simple example implementation of a callback handler that writes +the data to disk using the unique shader debug info identifier queried from the +opaque shader debug information blob. + +```C++ +// Handler for shader debug information callbacks (called by ShaderDebugInfoCallback) +void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) +{ + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Get shader debug information identifier. + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugInfoIdentifier(GFSDK_Aftermath_Version_API, pShaderDebugInfo, shaderDebugInfoSize, &identifier)); + + // Write to file for later in-depth analysis of crash dumps with Nsight Graphics. + WriteShaderDebugInformationToFile(identifier, pShaderDebugInfo, shaderDebugInfoSize); +} +``` + +By default, the shader debug information callback will be invoked for every +shader that is compiled by the NVIDIA display driver. It is the responsibility +of the implementation to handle those callbacks and store the data in case a GPU +crash occurs. To simplify the process the Nsight Aftermath library can handle +the caching of the debug information and only invoke the callback in case of a +GPU crash and only for the shaders referenced in the corresponding GPU crash +dump. This behavior is enabled by passing the +`GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks` flag to +`GFSDK_Aftermath_EnableGpuCrashDumps()` when enabling GPU crash dumps. + +Note that all callback functions are free-threaded; the application is +responsible for providing thread-safe callback handlers. + +## Disable GPU Crash Dumps + +To disable GPU crash dumps simply call `GFSDK_Aftermath_DisableGpuCrashDumps()`. + +```C++ + MyApp::~MyApp() + { + [...] + + // Disable GPU crash dump creation. + GFSDK_Aftermath_DisableGpuCrashDumps(); + + [...] + } +``` + +Disabling GPU crash dumps in an application with +`GFSDK_Aftermath_DisableGpuCrashDumps()` will re-enable any Nsight Aftermath GPU +crash dump monitor settings for this application, if it is running on the +system. After this, the GPU crash dump monitor will be notified of any GPU crash +related to this process and will create GPU crash dumps and shader debug +information files for all active devices. + +## Reading GPU Crash Dumps + +The Nsight Aftermath library provides several functions for decoding GPU crash +dumps and for querying data from the crash dumps. To use these functions +include the `GFSD_Aftermath_GpuCrashDumpDecoding.h` header file. + +The first step in decoding a GPU crash dump is to create a decoder object for +it by calling `GFSDK_Aftermath_GpuCrashDump_CreateDecoder()`: + +```C++ + // Create a GPU crash dump decoder object for the GPU crash dump. + GFSDK_Aftermath_GpuCrashDump_Decoder decoder = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_CreateDecoder( + GFSDK_Aftermath_Version_API, + pGpuCrashDump, + gpuCrashDumpSize, + &decoder)); +``` +Then one or more decoder functions can be used to read data from a GPU crash +dump. The data in the GPU crash dumps varies depending on the type of GPU crash +and the feature flags used when initializing Aftermath. For example, if the +application does not use Aftermath event markers, querying Aftermath event +marker information will fail. The decoder will return +`GFSDK_Aftermath_Result_NotAvailable` if the requested data is not available. +An implementation should be aware of that and handle the situation accordingly. + +Here is an example of how to query GPU page fault information from a GPU crash +dump using a previously created decoder object: + +```C++ + // Query GPU page fault information. + GFSDK_Aftermath_GpuCrashDump_PageFaultInfo pageFaultInfo = {}; + GFSDK_Aftermath_Result result = GFSDK_Aftermath_GpuCrashDump_GetPageFaultInfo(decoder, &pageFaultInfo); + + if (GFSDK_Aftermath_SUCCEED(result) && result != GFSDK_Aftermath_Result_NotAvailable) + { + // Print information about the GPU page fault. + Utility::Printf("GPU page fault at 0x%016llx", pageFaultInfo.faultingGpuVA); + if (pageFaultInfo.bHasResourceInfo) + { + Utility::Printf("Fault in resource starting at 0x%016llx", pageFaultInfo.resourceInfo.gpuVa); + Utility::Printf("Size of resource: (w x h x d x ml) = {%u, %u, %u, %u} = %llu bytes", + pageFaultInfo.resourceInfo.width, + pageFaultInfo.resourceInfo.height, + pageFaultInfo.resourceInfo.depth, + pageFaultInfo.resourceInfo.mipLevels, + pageFaultInfo.resourceInfo.size); + Utility::Printf("Format of resource: %u", pageFaultInfo.resourceInfo.format); + Utility::Printf("Resource was destroyed: %d", pageFaultInfo.resourceInfo.bWasDestroyed); + } + } +``` + +Some decoding functions require the caller to provide an appropriately sized +buffer for the data they return. Those come with an additional function to +query the size of the buffer. For example, querying all the active shaders at +the time of the GPU crash or hang could look like this: + +```C++ + // First query active shaders count. + uint32_t shaderCount = 0; + GFSDK_Aftermath_Result result = GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfoCount(decoder, &shaderCount); + + if (GFSDK_Aftermath_SUCCEED(result) && result != GFSDK_Aftermath_Result_NotAvailable) + { + // Allocate buffer for results. + std::vector shaderInfos(shaderCount); + + // Query active shaders information. + result = GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfo(decoder, shaderCount, shaderInfos.data()); + + if (GFSDK_Aftermath_SUCCEED(result)) + { + // Print information for each active shader + for (const GFSDK_Aftermath_GpuCrashDump_ShaderInfo& shaderInfo : shaderInfos) + { + Utility::Printf("Active shader: ShaderHash = 0x%016llx ShaderInstance = 0x%016llx Shadertype = %u", + shaderInfo.shaderHash, + shaderInfo.shaderInstance, + shaderInfo.shaderType); + } + } + } +``` + +Finally, the GPU crash dump decoder also provides functions for converting a GPU +crash dump into JSON format. Here is a code example for creating JSON from a GPU +crash dump including, information about all the shaders active at the time of +the GPU crash or hang. The infomration also includes the corresponding active +shader warps, including their mapping back to intermediate assembly language +(IL) instructions or source, if available. The later requires the caller to also +provide a couple of callback functions the decoder will invoke to query shader +debug information and shader binaries (dxc shader object outputs or SPIR-V +shader files). These are optional and implementations not interested in mapping +shader instruction addresses to IL or source lines can simply pass +`nullptr`. However, if shader instruction mapping is desired, the implementation +needs to ensure that it can provide the necessary information to the decoder. + +```C++ + // Flags controlling what to include in the JSON data + const uint32_t jsonDecoderFlags = + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_INFO | // Include information about active shaders. + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_WARP_STATE_INFO | // Include information about active shader warps. + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO; // Try to map shader instruction addresses to shader lines. + + // Query the size of the required results buffer + uint32_t jsonSize = 0; + GFSDK_Aftermath_Result result = GFSDK_Aftermath_GpuCrashDump_GenerateJSON( + decoder, + jsonDecoderFlags, // The flags controlling what information to include in the JSON. + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_CONDENSED_OUTPUT, // Generate condensed out, i.e. omit all unnecessary whitespace. + ShaderDebugInfoLookupCallback, // Callback function invoked to find shader debug information data. + ShaderLookupCallback, // Callback function invoked to find shader binary data by shader hash. + ShaderInstructionsLookupCallback, // Callback function invoked to find shader binary shader data by instructions hash. + ShaderSourceDebugDataLookupCallback, // Callback function invoked to find shader source debug data by shader DebugName. + &m_gpuCrashDumpTracker, // User data that will be provided to the above callback functions. + &jsonSize); // Result of the call: size in bytes of the generated JSON data. + + if (GFSDK_Aftermath_SUCCEED(result) && result != GFSDK_Aftermath_Result_NotAvailable) + { + // Allocate buffer for results. + std::vector json(jsonSize); + + // Query the generated JSON data taht si cached inside the decoder object. + result = GFSDK_Aftermath_GpuCrashDump_GetJSON( + decoder, + json.size(), + json.data()); + if (GFSDK_Aftermath_SUCCEED(result)) + { + Utility::Printf("JSON: %s", json.data()); + } + } +``` + +Possible implementations for the shader debug information and shader binary +lookup callbacks: + +```C++ + + // Static callback wrapper for OnShaderDebugInfoLookup + void MyApp::ShaderDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, + void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfoLookup(*pIdentifier, setShaderDebugInfo); + } + + // Static callback wrapper for OnShaderLookup + void MyApp::ShaderLookupCallback( + const GFSDK_Aftermath_ShaderHash* pShaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderLookup(*pShaderHash, setShaderBinary); + } + + // Static callback wrapper for OnShaderInstructionsLookup + void MyApp::ShaderInstructionsLookupCallback( + const GFSDK_Aftermath_ShaderInstructionsHash* pShaderInstructionsHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderInstructionsLookup(*pShaderInstructionsHash, setShaderBinary); + } + + // Static callback wrapper for OnShaderSourceDebugInfoLookup + void MyApp::ShaderSourceDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) + { + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary); + } + + // Handler for shader debug information lookup callbacks. + // This is used by the JSON decoder for mapping shader instruction + // addresses to IL lines or source lines. + void GpuCrashTracker::OnShaderDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const + { + // Search the list of shader debug information blobs received earlier. + auto i_debugInfo = m_shaderDebugInfo.find(identifier); + if (i_debugInfo == m_shaderDebugInfo.end()) + { + // Early exit, nothing found. No need to call setShaderDebugInfo. + return; + } + + // Let the GPU crash dump decoder know about the shader debug information + // that was found. + setShaderDebugInfo(i_debugInfo->second.data(), i_debugInfo->second.size()); + } + + // Handler for shader lookup callbacks. + // This is used by the JSON decoder for mapping shader instruction + // addresses to IL lines or source lines. + // NOTE: If the application loads stripped shader binaries, Aftermath + // will require access to both the stripped and the non-stripped + // shader binaries. + void GpuCrashTracker::OnShaderLookup( + const GFSDK_Aftermath_ShaderHash& shaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const + { + // Find shader binary data for the shader instruction hash in the shader database. + std::vector shaderBinary; + if (!m_shaderDatabase.FindShaderBinary(shaderInstructionsHash, shaderBinary)) + { + // Early exit, nothing found. No need to call setShaderBinary. + return; + } + + // Let the GPU crash dump decoder know about the shader data + // that was found. + setShaderBinary(shaderBinary.data(), shaderBinary.size()); + } + + // Handler for shader instructions lookup callbacks (D3D-only). + // This is used by the JSON decoder for mapping shader instruction + // addresses to DXIL lines or HLSL source lines. + // NOTE: If the application loads stripped shader binaries (-Qstrip_debug), + // Aftermath will require access to both the stripped and the non-stripped + // shader binaries. + void GpuCrashTracker::OnShaderInstructionsLookup( + const GFSDK_Aftermath_ShaderInstructionsHash& shaderInstructionsHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const + { + // Find shader binary data for the shader instruction hash in the shader database. + std::vector shaderBinary; + if (!m_shaderDatabase.FindShaderBinary(shaderInstructionsHash, shaderBinary)) + { + // Early exit, nothing found. No need to call setShaderBinary. + return; + } + + // Let the GPU crash dump decoder know about the shader data + // that was found. + setShaderBinary(shaderBinary.data(), shaderBinary.size()); + } + + // Handler for shader source debug info lookup callbacks. + // This is used by the JSON decoder for mapping shader instruction addresses to + // source lines, if the shaders used by the application were compiled with + // separate debug info data files. + void GpuCrashTracker::OnShaderSourceDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const + { + // Find source debug info for the shader DebugName in the shader database. + std::vector sourceDebugInfo; + if (!m_shaderDatabase.FindSourceShaderDebugData(shaderDebugName, sourceDebugInfo)) + { + // Early exit, nothing found. No need to call setShaderBinary. + return; + } + + // Let the GPU crash dump decoder know about the shader debug data that + // was found. + setShaderBinary(sourceDebugInfo.data(), sourceDebugInfo.size()); + } + +``` + +Last, the decoder object should be destroyed, if no longer needed, to free up +all memory allocated for it: + +```C++ + // Destroy the GPU crash dump decoder object. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder)); +``` + +# Shader Compilation for Source Mapping + +## D3D12 + +The following variants of generating source shader debug information for HLSL +shaders are supported: + +1. Compile and use full shader blobs + + Compile the shaders with the debug information. Use the full (i.e. not + stripped) shader binary when running the application and make it accessible + through `ShaderLookupCallback` and `ShaderInstructionsLookupCallback`. In + this case there is no need to provide a `ShaderSourceDebugDataLookupCallback`. + + Compilation example: + ``` + dxc -Zi [..] -Fo shader.bin shader.hlsl + ``` + +2. Compile and strip + + Compile the shaders with debug information and then strip off the debug + information. Use the stripped shader binary data when running the + application. Make the stripped shader binary data accessible through + `ShaderLookupCallback` and `ShaderInstructionsLookupCallback`. In addition, + make the non-stripped shader binary data accessible through + `ShaderSourceDebugDataLookupCallback`. + + Compilation example: + ``` + dxc -Zi [..] -Fo full_shader.bin shader.hlsl + dxc -dumpbin -Qstrip_debug -Fo shader.bin full_shader.bin + ``` + + The shader's DebugName required for implementing the + ShaderSourceDebugDataLookupCallback may be extracted from the stripped or + the non-stripped shader binary data with + `GFSDK_Aftermath_GetShaderDebugName()`. + +3. Compile with separate debug information (and auto-generated debug data file name) + + Compile the shaders with debug information and instruct the compiler to store + the debug meta data in a separate shader debug information file. The name of + the file generated by the compiler will match the DebugName of the shader. + Make the shader binary data accessible through `ShaderLookupCallback` and + `ShaderInstructionsLookupCallback`. In addition, make the data from the + compiler generated shader debug data file accessible through + `ShaderSourceDebugDataLookupCallback`. + + Compilation example: + ``` + dxc -Zi [..] -Fo shader.bin -Fd debugInfo\ shader.hlsl + ``` + + The debug data file generated by the compiler does not contain any reference + to the shader's DebugName. It is the responsibility of the user providing + the `ShaderSourceDebugDataLookupCallback` callback to implement a solution to + lookup the debug data based on the name of the generated debug data file. + +4. Compile with separate debug information (and user-defined debug data file name) + + Compile the shaders with debug information and instruct the compiler to + store the debug meta data in a separate shader debug information file. The + name of the file is freely choosen by the user. Make the shader binary data + accessible through `ShaderLookupCallback` and + `ShaderInstructionsLookupCallback`. In addition, make the data from the + compiler generated shader debug data file accessible through + `ShaderSourceDebugDataLookupCallback`. + + Compilation example: + ``` + dxc -Zi [..] -Fo shader.bin -Fd debugInfo\shader.dbg shader.hlsl + ``` + + The debug data file generated by the compiler does not contain any reference + to the shader's DebugName. It is the responsibility of the user providing + the `ShaderSourceDebugDataLookupCallback` callback to implement a solution + that performs the lookup of the debug data based on a mapping between the + shader's DebugName the debug data file's name that was chosen for the + compilation. The shader's DebugName may be extracted from the shader binary + data with `GFSDK_Aftermath_GetShaderDebugName()`. + +## Vulkan (SPIR-V) + +For SPIR-V shaders, the Aftermath SDK provides support for the following variants +of generating source shader debug information: + +1) Compile and use a full shader blob + Compile the shaders with the debug information. Use the full (i.e. not + stripped) shader binary when running the application and make it accessible + through `ShaderLookupCallback`. In this case there is no need to provide + ShaderInstructionsLookupCallback` or ShaderSourceDebugInfoLookupCallback`. + + Compilation example using the Vulkan SDK tool-chain: + ``` + glslangValidator -V -g -o ./full/shader.spv shader.vert + ``` + +2) Compile and strip + Compile the shaders with debug information and then strip off the debug + information. Use the stripped shader binary data when running the application. + Make the stripped shader binary data accessible through shaderLookupCb. + In addition, make the non-stripped shader binary data accessible through + `ShaderSourceDebugInfoLookupCallback`. + + Compilation example using the Vulkan SDK tool-chain: + ``` + glslangValidator -V -g -o ./full/shader.spv shader.vert + spirv-remap --map all --strip-all --input full/shader.spv --output ./stripped/ + ```` + + The (decoder) application then needs to pass the contents of the + `full/shader.spv` and `stripped/shader.spv` pair to + `GFSDK_Aftermath_GetDebugNameSpirv()` to generate the shader DebugName to + use with `ShaderSourceDebugInfoLookupCallback`. + +# Limitations and Known Issues + +* Nsight Aftermath covers only GPU crashes. CPU crashes in the NVIDIA display + driver, the D3D runtime, the Vulkan loader, or the application cannot be + captured. +* Nsight Aftermath is only fully supported on Turing or later GPUs. + +## D3D + +* Nsight Aftermath is only fully supported for D3D12 devices. Only basic support + with a reduced feature set (no resource tracking and no shader address + mapping) is available for D3D11 devcies. +* Nsight Aftermath is fully supported on Windows 10, with limited support on + Windows 7. +* Nsight Aftermath event markers and resource tracking is incompatible with the + D3D debug layer and tools using D3D API interception, such as Microsoft PIX + or Nsight Graphics. +* Shader line mappings for active warps are only supported for DXIL shaders, + i.e. Shader Model 6 or above. +* Due to a known driver bug the captured GPU state may be incomplete for + drivers < R440. This can affect the capturing of shader instruction addresses + for active warps. + +## Vulkan + +* On Linux, due to a driver limitation the device status reported by + `GFSDK_Aftermath_GpuCrashDump_GetDeviceInfo` is always + `GFSDK_Aftermath_Device_Status_Unknown`. This will be fixed in an upcoming + Linux display driver release. + +# Copyright and Licenses + +See LICENSE file. diff --git a/external/aftermath/include/GFSDK_Aftermath.h b/external/aftermath/include/GFSDK_Aftermath.h new file mode 100644 index 0000000..8a0de5b --- /dev/null +++ b/external/aftermath/include/GFSDK_Aftermath.h @@ -0,0 +1,483 @@ +/* +* Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +/* +* █████ █████ ██████ ████ ████ ███████ ████ ██████ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██████ ████ ██ ████ █████ ██ ██ ██ ██████ ██ ███████ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ DEBUGGER +* ██ ██ +* ████████████████████████████████████████████████████████ ██ █ ██ ████████████ +* +* +* HOW TO USE AFTERMATH for DX11 and DX12 +* -------------------------------------- +* +* Call 'GFSDK_Aftermath_DXxx_Initialize', to initialize the library and to enable +* the desired Aftermath feature set. See 'GFSDK_Aftermath_FeatureFlags' below for +* the list of supported features. +* This must be done before any other library calls are made, and the method must +* return 'GFSDK_Aftermath_Result_Success' for initialization to be complete. +* +* Initialization of Aftermath may fail for a variety of reasons, including: +* +* o) The initialization function was already called for the device: +* GFSDK_Aftermath_Result_FAIL_AlreadyInitialized. +* +* +* o) Aftermath isn't supported on the GPU associated with the device or the NVIDIA +* display driver version installed: +* GFSDK_Aftermath_Result_FAIL_InvalidAdapter, +* GFSDK_Aftermath_Result_FAIL_DriverInitFailed, +* GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported, +* GFSDK_Aftermath_Result_FAIL_NvApiIncompatible. +* +* +* o) A D3D API debug layer, such as PIX, was detected that is incompatible with +* Aftermath: +* GFSDK_Aftermath_Result_FAIL_D3dDllInterceptionNotSupported +* +* +* o) Aftermath was disabled on the system by the current user setting the +* 'HKEY_CURRENT_USER\Software\NVIDIA Corporation\Nsight Aftermath\ForceOff' +* Windows registry key: +* GFSDK_Aftermath_Result_FAIL_Disabled +* +* +* After detecting D3D device lost (TDR): +* +* o) To query the fault reason after TDR, use the 'GFSDK_Aftermath_GetDeviceStatus' +* call. See 'GFSDK_Aftermath_Device_Status', for the full list of possible +* status. +* +* +* o) In the event of a GPU page fault, use the'GFSDK_Aftermath_GetPageFaultInformation' +* method to return more information about what might of gone wrong. A GPU VA is +* returned, along with the resource descriptor of the resource that VA lands in. +* NOTE: It's not 100% certain that this is the resource which caused the fault, +* only that the faulting VA lands within this resource in memory. +* +* +* Optionally, instrument the application with Aftermath event markers: +* +* 1) For each commandlist/device context you expect to use with Aftermath, +* initialize them using the 'GFSDK_Aftermath_DXxx_CreateContextHandle', +* function. +* +* +* 2) Call 'GFSDK_Aftermath_SetEventMarker', to inject an event +* marker directly into the command stream at that point. +* +* PERFORMANCE TIP: +* +* Do not use 'GFSDK_Aftermath_SetEventMarker' in high frequency code paths. +* Injecting event markers introduces considerable CPU overhead. For reduced CPU +* overhead, use 'GFSDK_Aftermath_SetEventMarker' with markerSize=0. This +* instructs Aftermath not to allocate and copy off memory internally, relying on +* the application to manage marker pointers itself. +* +* +* 3) Once TDR/hang occurs, call the 'GFSDK_Aftermath_GetData' API +* to fetch the event marker last processed by the GPU for each context. +* This API also supports fetching the current execution state for each +* the GPU. +* +* +* 4) Before the app shuts down, each Aftermath context handle must be cleaned +* up, this is done with the 'GFSDK_Aftermath_ReleaseContextHandle' call. +* +* +* HOW TO USE AFTERMATH for Vulkan +* ------------------------------- +* +* For Vulkan use the VK_NV_device_diagnostics_config extension to initialize and +* configure the Aftermath feature set to use. +* +* Use the VK_NV_device_diagnostic_checkpoints extension to add event markers into +* the command stream. +* +*/ + +#ifndef GFSDK_Aftermath_H +#define GFSDK_Aftermath_H + +#include "GFSDK_Aftermath_Defines.h" + +#pragma pack(push, 8) + +#ifdef __cplusplus +extern "C" { +#endif + +// Here is defined a set of features that can be enabled/disable when using Aftermath +GFSDK_AFTERMATH_DECLARE_ENUM(FeatureFlags) +{ + // The minimal flag only allows use of the GetDeviceStatus entry point. + GFSDK_Aftermath_FeatureFlags_Minimum = 0x00000000, + + // With this flag set, the SetEventMarker and GetData entry points are available. + // + // Using event markers should be considered carefully as they can cause very high + // CPU overhead when used in high frequency code paths. + // + GFSDK_Aftermath_FeatureFlags_EnableMarkers = 0x00000001, + + // With this flag set, resources are tracked, and information about + // possible page fault candidates can be accessed using GetPageFaultInformation. + GFSDK_Aftermath_FeatureFlags_EnableResourceTracking = 0x00000002, + + // With this flag set, event markers are automatically set for all draw calls, + // compute dispatches and copy operations to capture the call stack for the + // corresponding API call as the event marker payload. + // Requires also GFSDK_Aftermath_FeatureFlags_EnableMarkers to be set. + // + // Using this option should be considered carefully. Enabling call stack capturing + // can cause considerable CPU overhead. + // + GFSDK_Aftermath_FeatureFlags_CallStackCapturing = 0x40000000, + + // With this flag set, shader debug information is generated. + // Not supported for UWP applications. + GFSDK_Aftermath_FeatureFlags_GenerateShaderDebugInfo = 0x00000008, + + // Use all Aftermath features + // Be careful when using this! Some features can cause considerable performance overhead, + // for example, GFSDK_Aftermath_FeatureFlags_EnableMarkers. + GFSDK_Aftermath_FeatureFlags_Maximum = GFSDK_Aftermath_FeatureFlags_Minimum | + GFSDK_Aftermath_FeatureFlags_EnableMarkers | + GFSDK_Aftermath_FeatureFlags_EnableResourceTracking | + GFSDK_Aftermath_FeatureFlags_CallStackCapturing | + GFSDK_Aftermath_FeatureFlags_GenerateShaderDebugInfo, +}; + +#if defined(__d3d11_h__) || defined(__d3d12_h__) + +// Used with Aftermath entry points to reference an API object. +GFSDK_AFTERMATH_DECLARE_HANDLE(GFSDK_Aftermath_ContextHandle); +GFSDK_AFTERMATH_DECLARE_HANDLE(GFSDK_Aftermath_ResourceHandle); + +// Used with, 'GFSDK_Aftermath_GetData'. Filled with information, +// about each requested context. +typedef struct GFSDK_Aftermath_ContextData +{ + GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(void*, markerData); + uint32_t markerSize; + GFSDK_Aftermath_Context_Status status; +} GFSDK_Aftermath_ContextData; + +// Minimal description of a graphics resource. +typedef struct GFSDK_Aftermath_ResourceDescriptor +{ + // This is available in DX12 only and only if the application registers the + // resource pointers using GFSDK_Aftermath_DX12_RegisterResource(). +#ifdef __d3d12_h__ + GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(ID3D12Resource*, pAppResource); +#else + GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(void*, pAppResource); +#endif + + uint64_t size; + + uint32_t width; + uint32_t height; + uint32_t depth; + + uint32_t mipLevels; + + uint32_t format; // DXGI_FORMAT + + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsBufferHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsStaticTextureHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsRtvDsvTextureHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bPlacedResource); + + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bWasDestroyed); +} GFSDK_Aftermath_ResourceDescriptor +; + +// Used with GFSDK_Aftermath_GetPageFaultInformation +typedef struct GFSDK_Aftermath_PageFaultInformation +{ + uint64_t faultingGpuVA; + GFSDK_Aftermath_ResourceDescriptor resourceDesc; + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bHasPageFaultOccured); +} GFSDK_Aftermath_PageFaultInformation; + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_DX11_Initialize +// GFSDK_Aftermath_DX12_Initialize +// --------------------------------- +// +// [pDx11Device]; DX11-Only +// the current dx11 device pointer. +// +// [pDx12Device]; DX12-Only +// the current dx12 device pointer. +// +// flags; +// set of features to enable when initializing Aftermath +// +// version; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking +// against library version. +// +//// DESCRIPTION; +// Library must be initialized before any other call is made. +// This should be done after device creation. +// Aftermath currently only supports one D3D device, +// the first one that is initialized. +// +///////////////////////////////////////////////////////////////////////// +#ifdef __d3d11_h__ +GFSDK_Aftermath_API GFSDK_Aftermath_DX11_Initialize(GFSDK_Aftermath_Version version, uint32_t flags, ID3D11Device* const pDx11Device); +#endif +#ifdef __d3d12_h__ +GFSDK_Aftermath_API GFSDK_Aftermath_DX12_Initialize(GFSDK_Aftermath_Version version, uint32_t flags, ID3D12Device* const pDx12Device); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_DX11_CreateContextHandle +// GFSDK_Aftermath_DX12_CreateContextHandle +// --------------------------------- +// +// (pDx11DeviceContext); DX11-Only +// Device context to use with Aftermath. +// +// (pDx12Unknown); DX12-Only +// Command list, Command Queue, or Device to use with Aftermath +// If a device, must be the same device given to GFSDK_Aftermath_DX12_Initialize() +// +// pOutContextHandle; +// The context handle for the specified context/command list/command queue/device +// to be used with future Aftermath calls. +// +//// DESCRIPTION; +// Before Aftermath event markers can be inserted, +// a context handle reference must first be fetched. +// +///////////////////////////////////////////////////////////////////////// +#ifdef __d3d11_h__ +GFSDK_Aftermath_API GFSDK_Aftermath_DX11_CreateContextHandle(ID3D11DeviceContext* const pDx11DeviceContext, GFSDK_Aftermath_ContextHandle* pOutContextHandle); +#endif +#ifdef __d3d12_h__ +GFSDK_Aftermath_API GFSDK_Aftermath_DX12_CreateContextHandle(IUnknown* const pDx12Unknown, GFSDK_Aftermath_ContextHandle* pOutContextHandle); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_API GFSDK_Aftermath_ReleaseContextHandle +// ------------------------------------- +// +// contextHandle; +// Context to release +// +// DESCRIPTION; +// Cleans up any resources associated with an Aftermath context +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_ReleaseContextHandle(const GFSDK_Aftermath_ContextHandle contextHandle); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_SetEventMarker +// ------------------------------------- +// +// contextHandle; +// Command list currently being populated. +// +// markerData; +// Pointer to data used for event marker. +// NOTE: If markerSize is also provided, an internal copy will be +// made of this data. In that case there is no need to keep it +// around after this call - stack alloc is safe. +// +// markerSize; +// Size of event marker data in bytes. +// NOTE: Passing a 0 for this parameter is valid, and will instruct +// Aftermath to only copy off the pointer supplied by markerData, +// rather than internally making a copy. This, however, precludes +// Aftermath from storing the marker data in GPU crash dumps. +// NOTE: Aftermath will internally truncate marker data to a maximum +// size of 1024 bytes. Use markerSize=0 and manually manage +// memory for markers if the application requires larger ones. +// +// DESCRIPTION; +// Drops a event into the command stream with a payload that can be +// linked back to the data given here, 'markerData'. It's +// safe to call from multiple threads simultaneously, normal D3D +// API threading restrictions apply. +// +// Using event markers should be considered carefully as they can cause considerable +// CPU overhead when used in high frequency code paths. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_SetEventMarker(const GFSDK_Aftermath_ContextHandle contextHandle, const void* markerData, const uint32_t markerSize); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetData +// ------------------------------ +// +// numContexts; +// Number of contexts to fetch information for. +// +// pContextHandles; +// Array of contexts containing Aftermath event markers. +// +// pOutContextData; +// OUTPUT: context data for each context requested. Contains event +// last reached on the GPU, and status of context if +// applicable (DX12-Only). +// NOTE: must allocate enough space for 'numContexts' worth of structures. +// stack allocation is fine. +// +// DESCRIPTION; +// Once a TDR/crash/hang has occurred (or whenever you like), call +// this API to retrieve the event last processed by the GPU on the +// given context. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GetData(const uint32_t numContexts, const GFSDK_Aftermath_ContextHandle* pContextHandles, GFSDK_Aftermath_ContextData* pOutContextData); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetContextError() +// ------------------------------ +// +// pContextData; +// Context data for which to determine error status. +// +// DESCRIPTION; +// Call this to determine the detailed failure reason for GFSDK_Aftermath_ContextData +// with 'status == GFSDK_Aftermath_Context_Status_Invalid'. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GetContextError(const GFSDK_Aftermath_ContextData* pContextData); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetDeviceStatus +// --------------------------------- +// +// pOutStatus; +// OUTPUT: Device status. +// +//// DESCRIPTION; +// Return the status of a D3D device. See GFSDK_Aftermath_Device_Status. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GetDeviceStatus(GFSDK_Aftermath_Device_Status* pOutStatus); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetPageFaultInformation +// --------------------------------- +// +// pOutPageFaultInformation; +// OUTPUT: Information about a page fault which may have occurred. +// +//// DESCRIPTION; +// Return any information available about a recent page fault which +// may have occurred, causing a device removed scenario. +// See GFSDK_Aftermath_PageFaultInformation. +// +// Requires WDDMv2 (Windows 10) or later +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GetPageFaultInformation(GFSDK_Aftermath_PageFaultInformation* pOutPageFaultInformation); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_DX12_RegisterResource +// --------------------------------- +// +// pResource; +// ID3D12Resource to register. +// +// pOutResourceHandle; +// OUTPUT: Aftermath resource handle for the resource that was registered. +// +//// DESCRIPTION; +// Register an ID3D12Resource with Aftermath. This allows Aftermath +// to map a GpuVA of a page fault to the corresponding ID3D12Resource. +// +// NOTE1: This function is only supported on Windows 10 RS4 and RS5. +// It will return GFSDK_Aftermath_Result_FAIL_D3dDllNotSupported, if the +// version of the D3D DLL is not supported. +// NOTE2: This function is not supported in UWP applications. +// NOTE3: This function is not compatible with graphics debuggers, such as +// Nsight Graphics or the Visual Studio Graphics Debugger. It may fail with +// GFSDK_Aftermath_Result_FAIL_D3dDllInterceptionNotSupported when called, +// if such a debugger is active. +// +// This is a BETA FEATURE and may not work with all versions of Windows. +// +///////////////////////////////////////////////////////////////////////// +#if defined(__d3d12_h__) +GFSDK_Aftermath_API GFSDK_Aftermath_DX12_RegisterResource(ID3D12Resource* const pResource, GFSDK_Aftermath_ResourceHandle* pOutResourceHandle); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_DX12_UnregisterResource +// --------------------------------- +// +// resourceHandle; +// Aftermath resource handle for a resource that was reagister earlier +// with GFSDK_Aftermath_DX12_RegisterResource(). +// +//// DESCRIPTION; +// Unregisters a previously registered resource. +// +// This is a BETA FEATURE and may not work with all versions of Windows. +// +///////////////////////////////////////////////////////////////////////// +#if defined(__d3d12_h__) +GFSDK_Aftermath_API GFSDK_Aftermath_DX12_UnregisterResource(const GFSDK_Aftermath_ResourceHandle resourceHandle); +#endif + +///////////////////////////////////////////////////////////////////////// +// +// NOTE: Function table provided - if dynamic loading is preferred. +// +///////////////////////////////////////////////////////////////////////// +#if defined(__d3d11_h__) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX11_Initialize)(GFSDK_Aftermath_Version version, uint32_t flags, ID3D11Device* const pDx11Device); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX11_CreateContextHandle)(ID3D11DeviceContext* const pDx11DeviceContext, GFSDK_Aftermath_ContextHandle* pOutContextHandle); +#endif + +#if defined(__d3d12_h__) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX12_Initialize)(GFSDK_Aftermath_Version version, uint32_t flags, ID3D12Device* const pDx12Device); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX12_CreateContextHandle)(IUnknown* const pDx12CommandList, GFSDK_Aftermath_ContextHandle* pOutContextHandle); +#endif + +#if defined(__d3d11_h__) || defined(__d3d12_h__) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ReleaseContextHandle)(const GFSDK_Aftermath_ContextHandle contextHandle); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_SetEventMarker)(const GFSDK_Aftermath_ContextHandle contextHandle, const void* markerData, const uint32_t markerSize); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetData)(const uint32_t numContexts, const GFSDK_Aftermath_ContextHandle* ppContextHandles, GFSDK_Aftermath_ContextData* pOutContextData); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetContextError)(const GFSDK_Aftermath_ContextData* pContextData); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetDeviceStatus)(GFSDK_Aftermath_Device_Status* pOutStatus); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetPageFaultInformation)(GFSDK_Aftermath_PageFaultInformation* pOutPageFaultInformation); +#endif + +#if defined(__d3d12_h__) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX12_RegisterResource)(ID3D12Resource* const pResource, GFSDK_Aftermath_ResourceHandle* pOutResourceHandle); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DX12_UnregisterResource)(const GFSDK_Aftermath_ResourceHandle resourceHandle); +#endif + +#endif // defined(__d3d11_h__) || defined(__d3d12_h__) + +#if defined(VULKAN_H_) +// See VK_NV_device_diagnostics_config +// See VK_NV_device_diagnostic_checkpoints + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#pragma pack(pop) + +#endif // GFSDK_Aftermath_H diff --git a/external/aftermath/include/GFSDK_Aftermath_Defines.h b/external/aftermath/include/GFSDK_Aftermath_Defines.h new file mode 100644 index 0000000..ed2ce62 --- /dev/null +++ b/external/aftermath/include/GFSDK_Aftermath_Defines.h @@ -0,0 +1,236 @@ +/* +* Copyright (c) 2016-2021, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +/* +* █████ █████ ██████ ████ ████ ███████ ████ ██████ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██████ ████ ██ ████ █████ ██ ██ ██ ██████ ██ ███████ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ DEBUGGER +* ██ ██ +* ████████████████████████████████████████████████████████ ██ █ ██ ████████████ +*/ + +#ifndef GFSDK_Aftermath_Defines_H +#define GFSDK_Aftermath_Defines_H + +#if defined(_MSC_VER) +#if defined(_M_X86) +#define GFSDK_AFTERMATH_CALL __cdecl +#else +#define GFSDK_AFTERMATH_CALL +#endif +#elif defined(__clang__) || defined(__GNUC__) +#if defined(__i386__) +#define GFSDK_AFTERMATH_CALL __attribute__((cdecl)) +#else +#define GFSDK_AFTERMATH_CALL +#endif +#else +#error "Unsupported compiler" +#endif + +#ifdef __cplusplus +#include +#else +#include +#include +#endif + +// Library stuff... +#define GFSDK_Aftermath_PFN typedef GFSDK_Aftermath_Result + +#if defined(_MSC_VER) +#ifdef EXPORTS +#define GFSDK_Aftermath_DLLSPEC __declspec(dllexport) +#else +#define GFSDK_Aftermath_DLLSPEC +#endif +#elif defined(__clang__) || defined(__GNUC__) +#define GFSDK_Aftermath_DLLSPEC __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +#define GFSDK_Aftermath_API extern "C" GFSDK_Aftermath_DLLSPEC GFSDK_Aftermath_Result GFSDK_AFTERMATH_CALL +#else +#define GFSDK_Aftermath_API GFSDK_Aftermath_DLLSPEC GFSDK_Aftermath_Result GFSDK_AFTERMATH_CALL +#endif + +#pragma pack(push, 8) + +// Helper macros for declare struct members and types with guaranteed properties +#define GFSDK_AFTERMATH_DECLARE_HANDLE(name) struct name##__ { int32_t ID; }; typedef struct name##__ *name +#ifdef __cplusplus +#define GFSDK_AFTERMATH_DECLARE_ENUM(name) enum GFSDK_Aftermath_##name : uint32_t +#else +#define GFSDK_AFTERMATH_DECLARE_ENUM(name) typedef uint32_t GFSDK_Aftermath_##name; enum GFSDK_Aftermath_##name +#endif +#define GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(type, name) union { type name; uint64_t ptr_align_##name; } +#define GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(name) union { bool name; uint32_t bool_align_##name; } + +GFSDK_AFTERMATH_DECLARE_ENUM(Version) +{ + GFSDK_Aftermath_Version_API = 0x000020b // Version 2.11 +}; + +GFSDK_AFTERMATH_DECLARE_ENUM(Result) +{ + GFSDK_Aftermath_Result_Success = 0x1, + + GFSDK_Aftermath_Result_NotAvailable = 0x2, + + GFSDK_Aftermath_Result_Fail = 0xBAD00000, + + // The callee tries to use a library version + // which does not match the built binary. + GFSDK_Aftermath_Result_FAIL_VersionMismatch = GFSDK_Aftermath_Result_Fail | 1, + + // The library hasn't been initialized, see; + // 'GFSDK_Aftermath_Initialize'. + GFSDK_Aftermath_Result_FAIL_NotInitialized = GFSDK_Aftermath_Result_Fail | 2, + + // The callee tries to use the library with + // a non-supported GPU. Currently, only + // NVIDIA GPUs are supported. + GFSDK_Aftermath_Result_FAIL_InvalidAdapter = GFSDK_Aftermath_Result_Fail | 3, + + // The callee passed an invalid parameter to the + // library, likely a null pointer or bad handle. + GFSDK_Aftermath_Result_FAIL_InvalidParameter = GFSDK_Aftermath_Result_Fail | 4, + + // Something weird happened that caused the + // library to fail for some reason. + GFSDK_Aftermath_Result_FAIL_Unknown = GFSDK_Aftermath_Result_Fail | 5, + + // Got a fail error code from the graphics API. + GFSDK_Aftermath_Result_FAIL_ApiError = GFSDK_Aftermath_Result_Fail | 6, + + // Make sure that the NvAPI DLL is up to date. + GFSDK_Aftermath_Result_FAIL_NvApiIncompatible = GFSDK_Aftermath_Result_Fail | 7, + + // It would appear as though a call has been + // made to fetch the Aftermath data for a + // context that hasn't been used with + // the EventMarker API yet. + GFSDK_Aftermath_Result_FAIL_GettingContextDataWithNewCommandList = GFSDK_Aftermath_Result_Fail | 8, + + // Looks like the library has already been initialized. + GFSDK_Aftermath_Result_FAIL_AlreadyInitialized = GFSDK_Aftermath_Result_Fail | 9, + + // Debug layer not compatible with Aftermath. + GFSDK_Aftermath_Result_FAIL_D3DDebugLayerNotCompatible = GFSDK_Aftermath_Result_Fail | 10, + + // Aftermath failed to initialize in the driver. + GFSDK_Aftermath_Result_FAIL_DriverInitFailed = GFSDK_Aftermath_Result_Fail | 11, + + // Aftermath v2.x requires driver version 387.xx and beyond + GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported = GFSDK_Aftermath_Result_Fail | 12, + + // The system ran out of memory for allocations + GFSDK_Aftermath_Result_FAIL_OutOfMemory = GFSDK_Aftermath_Result_Fail | 13, + + // No need to get data on bundles, as markers + // execute on the command list. + GFSDK_Aftermath_Result_FAIL_GetDataOnBundle = GFSDK_Aftermath_Result_Fail | 14, + + // No need to get data on deferred contexts, as markers + // execute on the immediate context. + GFSDK_Aftermath_Result_FAIL_GetDataOnDeferredContext = GFSDK_Aftermath_Result_Fail | 15, + + // This feature hasn't been enabled at initialization - see GFSDK_Aftermath_FeatureFlags. + GFSDK_Aftermath_Result_FAIL_FeatureNotEnabled = GFSDK_Aftermath_Result_Fail | 16, + + // No resources have ever been registered. + GFSDK_Aftermath_Result_FAIL_NoResourcesRegistered = GFSDK_Aftermath_Result_Fail | 17, + + // This resource has never been registered. + GFSDK_Aftermath_Result_FAIL_ThisResourceNeverRegistered = GFSDK_Aftermath_Result_Fail | 18, + + // The functionality is not supported for UWP applications + GFSDK_Aftermath_Result_FAIL_NotSupportedInUWP = GFSDK_Aftermath_Result_Fail | 19, + + // D3D DLL not compatible with Aftermath. + GFSDK_Aftermath_Result_FAIL_D3dDllNotSupported = GFSDK_Aftermath_Result_Fail | 20, + + // D3D DLL interception is not compatible with Aftermath. + GFSDK_Aftermath_Result_FAIL_D3dDllInterceptionNotSupported = GFSDK_Aftermath_Result_Fail | 21, + + // Aftermath is disabled on the system by the current user. + // On Windows, this is controlled by a Windows registry key: + // KeyPath : HKEY_CURRENT_USER\Software\NVIDIA Corporation\Nsight Aftermath + // KeyValue : ForceOff + // ValueType : REG_DWORD + // ValueData : Any value != 0 will force the functionality of the Aftermath + // SDK off on the system. + // + // On Linux, this is controlled by an environment variable: + // Name: NV_AFTERMATH_FORCE_OFF + // Value: Any value != '0' will force the functionality of the Aftermath + // SDK off. + // + GFSDK_Aftermath_Result_FAIL_Disabled = GFSDK_Aftermath_Result_Fail | 22, +}; + +#define GFSDK_Aftermath_SUCCEED(value) (((value) & 0xFFF00000) != GFSDK_Aftermath_Result_Fail) + +GFSDK_AFTERMATH_DECLARE_ENUM(Context_Status) +{ + // GPU: + // The GPU has not started processing this command list yet. + GFSDK_Aftermath_Context_Status_NotStarted = 0, + + // This command list has begun execution on the GPU. + GFSDK_Aftermath_Context_Status_Executing, + + // This command list has finished execution on the GPU. + GFSDK_Aftermath_Context_Status_Finished, + + // This context has an invalid state, which could be + // caused by an error. + // + // NOTE: See, 'GFSDK_Aftermath_ContextData::getErrorCode()' + // for more information. + GFSDK_Aftermath_Context_Status_Invalid, +}; + +GFSDK_AFTERMATH_DECLARE_ENUM(Device_Status) +{ + // The GPU is still active, and hasn't gone down. + GFSDK_Aftermath_Device_Status_Active = 0, + + // A long running shader/operation has caused a + // GPU timeout. Reconfiguring the timeout length + // might help tease out the problem. + GFSDK_Aftermath_Device_Status_Timeout, + + // Run out of memory to complete operations. + GFSDK_Aftermath_Device_Status_OutOfMemory, + + // An invalid VA access has caused a fault. + GFSDK_Aftermath_Device_Status_PageFault, + + // The GPU has stopped executing + GFSDK_Aftermath_Device_Status_Stopped, + + // The device has been reset + GFSDK_Aftermath_Device_Status_Reset, + + // Unknown problem - likely using an older driver + // incompatible with this Aftermath feature. + GFSDK_Aftermath_Device_Status_Unknown, + + // An invalid rendering call has percolated through the driver + GFSDK_Aftermath_Device_Status_DmaFault, +}; + +#pragma pack(pop) + +#endif // GFSDK_Aftermath_Defines_H diff --git a/external/aftermath/include/GFSDK_Aftermath_GpuCrashDump.h b/external/aftermath/include/GFSDK_Aftermath_GpuCrashDump.h new file mode 100644 index 0000000..333aadf --- /dev/null +++ b/external/aftermath/include/GFSDK_Aftermath_GpuCrashDump.h @@ -0,0 +1,232 @@ +/* +* Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +/* +* █████ █████ ██████ ████ ████ ███████ ████ ██████ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██████ ████ ██ ████ █████ ██ ██ ██ ██████ ██ ███████ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ DEBUGGER +* ██ ██ +* ████████████████████████████████████████████████████████ ██ █ ██ ████████████ +* +* +* HOW TO USE AFTERMATH GPU CRASH DUMP COLLECTION: +* ----------------------------------------------- +* +* 1) Call 'GFSDK_Aftermath_EnableGpuCrashDumps', to enable GPU crash dump collection. +* This must be done before any other library calls are made and before any D3D +* device is created by the application. +* +* With this call the application can register a callback function that is invoked +* with the GPU crash dump data once a TDR/hang occurs. In addition, it is also +* possible to provide optional callback functions for collecting shader debug +* information and for providing additional descriptive data from the application to +* include in the crash dump. +* +* Enabling GPU crash dumps will also override any settings from an also active +* Nsight Graphics GPU crash dump monitor for the calling process. +* +* +* 2) On DX11/DX12, call 'GFSDK_Aftermath_DXxx_Initialize', to initialize the library and +* to enable additional Aftermath features that will affect the data captured in the +* GPU crash dumps, such as Aftermath event markers; automatic call stack markers for +* all draw calls, compute dispatches, ray dispatches, or copy operations; resource +* tracking; or shader debug information. See GFSDK_Aftermath.h for more details. +* +* On Vulkan use the VK_NV_device_diagnostics_config extension to enable additional +* Aftermath features, such as automatic call stack markers for all draw calls, compute +* dispatches, ray dispatches, or copy operations; resource tracking; or shader debug +* information. See GFSDK_Aftermath.h for more details. +* +* +* 4) Before the application shuts down, call 'GFSDK_Aftermath_DisableGpuCrashDumps' to +* disable GPU crash dump collection. +* +* Disabling GPU crash dumps will also re-establish any settings from an also active +* Nsight Graphics GPU crash dump monitor for the calling process. +* +* +* OPTIONAL: +* +* o) (Optional) Instrument the application with event markers as described in +* GFSDK_Aftermath.h. +* o) (Optional, D3D12) Register D3D12 resource pointers with Aftermath as described in +* GFSDK_Aftermath.h. +* o) (Optional) To disable all GPU crash dump functionality at runtime: +* On Windows, set the registry key: 'HKEY_CURRENT_USER\Software\NVIDIA Corporation\Nsight Aftermath\ForceOff'. +* On Linux, set environment 'NV_AFTERMATH_FORCE_OFF'. +* +* +* PERFORMANCE TIPS: +* +* o) Enabling shader debug information creation will introduce shader compile time +* overhead as well as memory overhead for handling the debug information. +* +* o) User event markers cause considerable overhead and should be used very carefully. +* Using automatic callstack markers for draw calls, compute dispatches, ray dispatches, +* and copy operations may be a less costly alternative to injecting an event marker for +* every draw call. However, they also do not come for free and using them should be +* also considered carefully. +* +*/ + +#ifndef GFSDK_Aftermath_GpuCrashDump_H +#define GFSDK_Aftermath_GpuCrashDump_H + +#include "GFSDK_Aftermath_Defines.h" + +#pragma pack(push, 8) + +#ifdef __cplusplus +extern "C" { +#endif + +// Flags to configure for which graphisc APIs to enable GPU crash dumps +GFSDK_AFTERMATH_DECLARE_ENUM(GpuCrashDumpWatchedApiFlags) +{ + // Default setting + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_None = 0x0, + + // Enable GPU crash dump tracking for the DX API + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_DX = 0x1, + + // Enable GPU crash dump tracking for the Vulkan API + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan = 0x2, +}; + +// Flags to configure GPU crash dump-specific Aftermath features +GFSDK_AFTERMATH_DECLARE_ENUM(GpuCrashDumpFeatureFlags) +{ + // Default settings + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_Default = 0x0, + + // Defer shader debug information callbacks until an actual GPU crash + // dump is generated and also provide shader debug information + // for the shaders related to the crash dump only. + // Note: using this option will increase the memory footprint of the + // application. + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks = 0x1, +}; + +// Key definitions for user-defined GPU crash dump description +GFSDK_AFTERMATH_DECLARE_ENUM(GpuCrashDumpDescriptionKey) +{ + // Predefined key for application name + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName = 0x00000001, + + // Predefined key for application version + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion = 0x00000002, + + // Base key for creating user-defined key-value pairs. + // Any value >= GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + // will create a user-defined key-value pair. + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined = 0x00010000, +}; + +// Function for adding user-defined description key-value pairs. +// Key must be one of the predefined keys of GFSDK_Aftermath_GpuCrashDumpDescriptionKey +// or a user-defined key based on GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined. +// All keys greater than the last predefined key in GFSDK_Aftermath_GpuCrashDumpDescriptionKey +// and smaller than GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined are +// considered illegal and ignored. +typedef void (GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription)(uint32_t key, const char* value); + +// GPU crash dump callback definitions. +// NOTE: Except for the pUserData pointer, all pointer values passed to the +// callbacks are only valid for the duration of the call! An implementation +// must make copies of the data, if it intends to store it beyond that. +typedef void (GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDumpCb)(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize, void* pUserData); +typedef void (GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ShaderDebugInfoCb)(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize, void* pUserData); +typedef void (GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDumpDescriptionCb)(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addValue, void* pUserData); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_EnableGpuCrashDumps +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// watchedApis; +// Controls which graphics APIs to watch for crashes. A combination (with OR) of +// GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags. +// +// flags; +// Controls GPU crash dump specific behavior. A combination (with OR) of +// GFSDK_Aftermath_GpuCrashDumpFeatureFlags. +// +// gpuCrashDumpCb; +// Callback function to be called when new GPU crash dump data is available. +// Callback is free-threaded, ensure the provided function is thread-safe. +// +// shaderDebugInfoCb; +// Callback function to be called when new shader debug information data is +// available. +// Callback is free-threaded, ensure the provided function is thread-safe. +// Optional, can be NULL. +// Note: if not using GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks +// shaderDebugInfoCb will be invoked for every shader compilation trigegred by the +// application, even if there will be never an invocation of gpuCrashDumpCb. +// +// descriptionCb; +// Callback function that allows the application to provide additional +// descriptive values to be include in crash dumps. This will be called +// before gpuCrashDumpCb. +// Callback is free-threaded, ensure the provided function is thread-safe. +// Optional, can be NULL. +// +// pUserData; +// User data made available in the callbacks. +// +//// DESCRIPTION; +// Device independent initialization call to enable Aftermath GPU crash dump +// creation. Overrides any settings from an also active GPU crash dump monitor +// for this process! This function must be called before any D3D device is +// created by the application. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_EnableGpuCrashDumps( + GFSDK_Aftermath_Version apiVersion, + uint32_t watchedApis, + uint32_t flags, + PFN_GFSDK_Aftermath_GpuCrashDumpCb gpuCrashDumpCb, + PFN_GFSDK_Aftermath_ShaderDebugInfoCb shaderDebugInfoCb, + PFN_GFSDK_Aftermath_GpuCrashDumpDescriptionCb descriptionCb, + void* pUserData); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_DisableGpuCrashDumps +// --------------------------------- +// +//// DESCRIPTION; +// Device independent call to disable Aftermath GPU crash dump creation. +// Re-enables settings from an also active GPU crash dump monitor for +// the current process! +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_DisableGpuCrashDumps(); + +///////////////////////////////////////////////////////////////////////// +// +// NOTE: Function table provided - if dynamic loading is preferred. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_EnableGpuCrashDumps)(GFSDK_Aftermath_Version apiVersion, uint32_t watchedApis, uint32_t flags, PFN_GFSDK_Aftermath_GpuCrashDumpCb gpuCrashDumpCb, PFN_GFSDK_Aftermath_ShaderDebugInfoCb shaderDebugInfoCb, PFN_GFSDK_Aftermath_GpuCrashDumpDescriptionCb descriptionCb, void* pUserData); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_DisableGpuCrashDumps)(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#pragma pack(pop) + +#endif // GFSDK_Aftermath_GpuCrashDump_H diff --git a/external/aftermath/include/GFSDK_Aftermath_GpuCrashDumpDecoding.h b/external/aftermath/include/GFSDK_Aftermath_GpuCrashDumpDecoding.h new file mode 100644 index 0000000..de61b7b --- /dev/null +++ b/external/aftermath/include/GFSDK_Aftermath_GpuCrashDumpDecoding.h @@ -0,0 +1,982 @@ +/* +* Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an express +* license agreement from NVIDIA CORPORATION is strictly prohibited. +*/ + +/* +* █████ █████ ██████ ████ ████ ███████ ████ ██████ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██████ ████ ██ ████ █████ ██ ██ ██ ██████ ██ ███████ +* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ +* ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ DEBUGGER +* ██ ██ +* ████████████████████████████████████████████████████████ ██ █ ██ ████████████ +* +* +* HOW TO DECODE AFTERMATH GPU CRASH DUMPS: +* ---------------------------------------- +* +* 1) Call 'GFSDK_Aftermath_GpuCrashDump_CreateDecoder', to create a decoder object for +* a GPU crash dump. +* +* +* 2) Call one or more of the 'GFSDK_Aftermath_GpuCrashDump_Get*' functions with this +* decoder, to query information from the GPU crash dump. +* +* Some of the functions require caller allocated buffers to return the data. Those +* are accompanied with a corresponding 'GFSDK_Aftermath_GpuCrashDump_Get*Count()' +* function to query the element count the caller has to reserve for these buffers. +* +* If the requested data is not avilable in the crash dump the functions will return +* with GFSDK_Aftermath_Result_NotAvailable. +* +* +* 3) Call 'GFSDK_Aftermath_GpuCrashDump_DestroyDecoder', to destroy the decoder object +* and cleanup all related memory. +* +*/ + +#ifndef GFSDK_Aftermath_CrashDumpDecoding_H +#define GFSDK_Aftermath_CrashDumpDecoding_H + +#include "GFSDK_Aftermath_Defines.h" + +#pragma pack(push, 8) + +#ifdef __cplusplus +extern "C" { +#endif + +// Constants used in crash dump decoding functions +enum +{ + GFSDK_Aftermath_MAX_STRING_LENGTH = 127, +}; + +// Unique identifier for shader debug information +typedef struct GFSDK_Aftermath_ShaderDebugInfoIdentifier +{ + uint64_t id[2]; +} GFSDK_Aftermath_ShaderDebugInfoIdentifier; + +// Unique identifier for shader binaries +typedef struct GFSDK_Aftermath_ShaderHash +{ + uint64_t hash; +} GFSDK_Aftermath_ShaderHash; + +// Unique identifier for shader instructions +typedef struct GFSDK_Aftermath_ShaderInstructionsHash +{ + uint64_t hash; +} GFSDK_Aftermath_ShaderInstructionsHash; + +// Shader DebugName, i.e. a unique identifier for shader source debug information +typedef struct GFSDK_Aftermath_ShaderDebugName +{ + char name[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; +} GFSDK_Aftermath_ShaderDebugName; + +// SPIR-V shader code +#if defined(VULKAN_H_) +typedef struct GFSDK_Aftermath_SpirvCode +{ + GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(void*, pData); + uint32_t size; +} GFSDK_Aftermath_SpirvCode; +#endif + +// Graphics API +GFSDK_AFTERMATH_DECLARE_ENUM(GraphicsApi) +{ + GFSDK_Aftermath_GraphicsApi_Unknown = 0, + GFSDK_Aftermath_GraphicsApi_D3D_10_0 = 1, + GFSDK_Aftermath_GraphicsApi_D3D_10_1 = 2, + GFSDK_Aftermath_GraphicsApi_D3D_11_0 = 3, + GFSDK_Aftermath_GraphicsApi_D3D_11_1 = 4, + GFSDK_Aftermath_GraphicsApi_D3D_11_2 = 5, + GFSDK_Aftermath_GraphicsApi_D3D_12_0 = 6, + GFSDK_Aftermath_GraphicsApi_Vulkan = 7, +}; + +// GPU crash dump - base information +typedef struct GFSDK_Aftermath_GpuCrashDump_BaseInfo +{ + char applicationName[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; + char creationDate[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; + uint32_t pid; + GFSDK_Aftermath_GraphicsApi graphicsApi; +} GFSDK_Aftermath_GpuCrashDump_BaseInfo; + +// GPU crash dump - device information +typedef struct GFSDK_Aftermath_GpuCrashDump_DeviceInfo +{ + GFSDK_Aftermath_Device_Status status; + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(adapterReset); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(channel3dReset); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(channelComputeReset); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(channelCopyReset); +} GFSDK_Aftermath_GpuCrashDump_DeviceInfo; + +// GPU crash dump - system information +typedef struct GFSDK_Aftermath_GpuCrashDump_SystemInfo +{ + char osVersion[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; + struct DisplayDriverVersion + { + uint32_t major; + uint32_t minor; + } displayDriver; +} GFSDK_Aftermath_GpuCrashDump_SystemInfo; + +// GPU crash dump - GPU information +typedef struct GFSDK_Aftermath_GpuCrashDump_GpuInfo +{ + char adapterName[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; + char generationName[GFSDK_Aftermath_MAX_STRING_LENGTH + 1]; + uint64_t adapterLUID; +} GFSDK_Aftermath_GpuCrashDump_GpuInfo; + +// GPU crash dump - page fault information +typedef struct GFSDK_Aftermath_GpuCrashDump_PageFaultInfo +{ + uint64_t faultingGpuVA; + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bHasResourceInfo); + struct ResourceInfo { + uint64_t gpuVa; + + uint64_t size; + + uint32_t width; + uint32_t height; + uint32_t depth; + + uint32_t mipLevels; + + uint32_t format; // DXGI_Format for DX, VkFormat for Vulkan + + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsBufferHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsStaticTextureHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bIsRenderTargetOrDepthStencilViewHeap); + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bPlacedResource); + + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(bWasDestroyed); + uint32_t createDestroyTickCount; + } resourceInfo; +} GFSDK_Aftermath_GpuCrashDump_PageFaultInfo; + +// GPU crash dump - shader types +GFSDK_AFTERMATH_DECLARE_ENUM(ShaderType) +{ + GFSDK_Aftermath_ShaderType_Unknown = 0, + GFSDK_Aftermath_ShaderType_Vertex, + GFSDK_Aftermath_ShaderType_Tessellation_Control, + GFSDK_Aftermath_ShaderType_Hull = GFSDK_Aftermath_ShaderType_Tessellation_Control, + GFSDK_Aftermath_ShaderType_Tessellation_Evaluation, + GFSDK_Aftermath_ShaderType_Domain = GFSDK_Aftermath_ShaderType_Tessellation_Evaluation, + GFSDK_Aftermath_ShaderType_Geometry, + GFSDK_Aftermath_ShaderType_Fragment, + GFSDK_Aftermath_ShaderType_Pixel = GFSDK_Aftermath_ShaderType_Fragment, + GFSDK_Aftermath_ShaderType_Compute, + GFSDK_Aftermath_ShaderType_RayTracing_RayGeneration, + GFSDK_Aftermath_ShaderType_RayTracing_Miss, + GFSDK_Aftermath_ShaderType_RayTracing_Intersection, + GFSDK_Aftermath_ShaderType_RayTracing_AnyHit, + GFSDK_Aftermath_ShaderType_RayTracing_ClosestHit, + GFSDK_Aftermath_ShaderType_RayTracing_Callable, + GFSDK_Aftermath_ShaderType_RayTracing_Internal, + GFSDK_Aftermath_ShaderType_Mesh, + GFSDK_Aftermath_ShaderType_Task, +}; + +// GPU crash dump - shader information +typedef struct GFSDK_Aftermath_GpuCrashDump_ShaderInfo +{ + uint64_t shaderHash; + uint64_t shaderInstance; + GFSDK_AFTERMATH_DECLARE_BOOLEAN_MEMBER(isInternal); + GFSDK_Aftermath_ShaderType shaderType; +} GFSDK_Aftermath_GpuCrashDump_ShaderInfo; + +// GPU crash dump - Event marker context type +GFSDK_AFTERMATH_DECLARE_ENUM(Context_Type) +{ + GFSDK_Aftermath_Context_Type_Invalid = 0, + GFSDK_Aftermath_Context_Type_Immediate, + GFSDK_Aftermath_Context_Type_CommandList, + GFSDK_Aftermath_Context_Type_Bundle, + GFSDK_Aftermath_Context_Type_CommandQueue +}; + +// GPU crash dump - Event marker data ownership +GFSDK_AFTERMATH_DECLARE_ENUM(EventMarkerDataOwnership) +{ + // Data is owned by the user application + GFSDK_Aftermath_EventMarkerDataOwnership_User = 0, + + // Data is part of the crash dump and is owned by the decoder + GFSDK_Aftermath_EventMarkerDataOwnership_Decoder, +}; + +// GPU crash dump - Aftermath event marker information +// NOTE: If GFSDK_Aftermath_SetEventMarker was called with markerSize=0, +// markerDataOwnership will be set to GFSDK_Aftermath_EventMarkerDataOwnership_User +// and the markerData pointer will be only valid within the context of the process +// setting the marker and if the application properly manages the lifetime of the +// pointed to data. It is the responsibility of the caller to ensure that the pointer +// is valid before accessing the pointed to data. +typedef struct GFSDK_Aftermath_GpuCrashDump_EventMarkerInfo +{ + uint64_t contextId; + GFSDK_Aftermath_Context_Status contextStatus; + GFSDK_Aftermath_Context_Type contextType; + GFSDK_AFTERMATH_DECLARE_POINTER_MEMBER(const void*, markerData); + GFSDK_Aftermath_EventMarkerDataOwnership markerDataOwnership; + uint32_t markerDataSize; +} GFSDK_Aftermath_GpuCrashDump_EventMarkerInfo; + +// Flags that control the behavior of GFSDK_Aftermath_GpuCrashDump_GenerateJSON +GFSDK_AFTERMATH_DECLARE_ENUM(GpuCrashDumpDecoderFlags) +{ + // Include basic information about the GPU crash dump. + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_BASE_INFO = 0x1, + + // Include information about the device state + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_DEVICE_INFO = 0x2, + + // Include information about the OS + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_OS_INFO = 0x4, + + // Include information about the display driver + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_DISPLAY_DRIVER_INFO = 0x8, + + // Include information about the GPU + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_GPU_INFO = 0x10, + + // Include information about page faults (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_PAGE_FAULT_INFO = 0x20, + + // Include information about shaders (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_INFO = 0x40, + + // Include information about active warps (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_WARP_STATE_INFO = 0x80, + + // Try to map shader addresses to source or intermediate assembly lines + // using additional information provided through shaderDebugInfoLookupCb, + // shaderLookupCb and shaderInstructionsLookupCb, if provided. + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO = 0x100, + + // Include Aftermath event marker data (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_EVENT_MARKER_INFO = 0x200, + + // Include automatic event marker call stack data (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_CALL_STACK_INFO = 0x400, + + // Include user provided GPU crash dump description values (if available) + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_DESCRIPTION_INFO = 0x800, + + // Include all available information + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO= 0xFFF, +}; + +GFSDK_AFTERMATH_DECLARE_ENUM(GpuCrashDumpFormatterFlags) +{ + // No special formatting + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE = 0x0, + + // Remove all unnecessary whitespace from formatted string + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_CONDENSED_OUTPUT = 0x1, + + // Use UTF8 encoding + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_UTF8_OUTPUT = 0x2, +}; + +// Crash dump decoder handle +GFSDK_AFTERMATH_DECLARE_HANDLE(GFSDK_Aftermath_GpuCrashDump_Decoder); + +// Function for providing shader debug information and shader binary to the crash dump decoder +typedef void(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_SetData)(const void* pData, uint32_t size); + +// GPU crash dump decoder callback definitions +typedef void(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ShaderDebugInfoLookupCb)(const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, void* pUserData); +typedef void(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ShaderLookupCb)(const GFSDK_Aftermath_ShaderHash* pShaderHash, PFN_GFSDK_Aftermath_SetData setShaderBinary, void* pUserData); +typedef void(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ShaderInstructionsLookupCb)(const GFSDK_Aftermath_ShaderInstructionsHash* pShaderInstructionsHash, PFN_GFSDK_Aftermath_SetData setShaderBinary, void* pUserData); +typedef void(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_ShaderSourceDebugInfoLookupCb)(const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, PFN_GFSDK_Aftermath_SetData setShaderBinary, void* pUserData); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_CreateDecoder +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pGpuCrashDump; +// Pointer to GPU crash dump data captured in a GFSDK_Aftermath_GpuCrashDumpCb +// callback. +// +// gpuCrashDumpSize; +// Size of GPU crash dump data in bytes. +// +// pDecoder; +// Pointer to a decoder object owned by the caller that is initialized. +// +//// DESCRIPTION; +// Create a decoder object that can be used to query information about the +// provided GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_CreateDecoder( + GFSDK_Aftermath_Version apiVersion, + const void* pGpuCrashDump, + const uint32_t gpuCrashDumpSize, + GFSDK_Aftermath_GpuCrashDump_Decoder* pDecoder); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_DestroyDecoder +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +//// DESCRIPTION; +// Free any data related to the passed in decoder object. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_DestroyDecoder( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetBaseInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pBaseInfo; +// Pointer to data structure owned by the caller that is filled in with +// information from the GPU crash dump. +// +//// DESCRIPTION; +// Query basic information from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetBaseInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + GFSDK_Aftermath_GpuCrashDump_BaseInfo* pBaseInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// key; +// What value to query from the description section. +// +// pValueSize; +// Populated with the size of the value in bytes (including 0-termination +// of the string). +// +//// DESCRIPTION; +// Query the size of a description value from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t key, + uint32_t* pValueSize); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetDescription +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// key; +// What value to query from the description section. +// +// valueBufferSize; +// Size in bytes of the caller allocated results buffer pValue. +// +// pValue; +// Caller allocated results buffer. +// +//// DESCRIPTION; +// Query description value from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetDescription( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t key, + const uint32_t valueBufferSize, + char* pValue); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetDeviceInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pDeviceInfo; +// Pointer to data structure owned by the caller that is filled in with +// information from the GPU crash dump. +// +//// DESCRIPTION; +// Query device state information from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetDeviceInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + GFSDK_Aftermath_GpuCrashDump_DeviceInfo* pDeviceInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetSystemInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pSystemInfo; +// Pointer to data structure owned by the caller that is filled in with +// information from the GPU crash dump. +// +//// DESCRIPTION; +// Query system information (OS, display driver) from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetSystemInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + GFSDK_Aftermath_GpuCrashDump_SystemInfo* pSystemInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetGpuInfoCount +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pGpuCount; +// Populated with the number of GPU entries in the GPU crash dump. +// +//// DESCRIPTION; +// Query number of GPU entries from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetGpuInfoCount( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + uint32_t* pGpuCount); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetGpuInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// gpuInfoBufferCount; +// Number of elements in caller allocated array passed in pGpuInfo. +// +// pGpuInfo; +// Pointer to caller allocated array of GFSDK_Aftermath_GpuCrashDump_GpuInfo +// that is filled in with information from the GPU crash dump. +// +//// DESCRIPTION; +// Query information about the GPUs from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetGpuInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t gpuInfoBufferCount, + GFSDK_Aftermath_GpuCrashDump_GpuInfo* pGpuInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetPageFaultInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pPageFaultInfo; +// Pointer to data structure owned by the caller that is filled in with +// information from the GPU crash dump. +// +//// DESCRIPTION; +// Query page fault information from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetPageFaultInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + GFSDK_Aftermath_GpuCrashDump_PageFaultInfo* pPageFaultInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfoCount +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pShaderCount; +// Populated with the number of active shaders in the GPU crash dump. +// +//// DESCRIPTION; +// Query the number of active shaders from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfoCount( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + uint32_t* pShaderCount); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// shaderInfoBufferCount; +// Number of elements in caller allocated array passed in pShaderInfo. +// +// pShaderInfo; +// Pointer to caller allocated array of GFSDK_Aftermath_GpuCrashDump_ShaderInfo +// that is filled in with information from the GPU crash dump. +// +//// DESCRIPTION; +// Query information about active shaders from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t shaderInfoBufferCount, + GFSDK_Aftermath_GpuCrashDump_ShaderInfo* pShaderInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfoCount +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// pMarkerCount; +// Populated with the number of event markers in the GPU crash dump. +// +//// DESCRIPTION; +// Query the number of event markers from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfoCount( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + uint32_t* pMarkerCount); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfo +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// markerInfoBufferCount; +// Number of elements in caller allocated array passed in pMarkerInfo. +// +// pMarkerInfo; +// Pointer to caller allocated array of GFSDK_Aftermath_GpuCrashDump_EventMarkerInfo +// that is filled in with information from the GPU crash dump. +// +//// DESCRIPTION; +// Query information about event markers from a GPU crash dump. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfo( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t markerInfoBufferCount, + GFSDK_Aftermath_GpuCrashDump_EventMarkerInfo* pMarkerInfo); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GenerateJSON +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// decoderFlags; +// Flags that define what information to include in the decoding. Bitwise OR of any +// of the flags defined in GFSDK_Aftermath_GpuCrashDumpDecoderFlags. +// +// formatFlags; +// Flags controlling the formatting. Bitwise OR of any of the flags defined in +// GFSDK_Aftermath_GpuCrashDumpFormatterFlags. +// +// shaderDebugInfoLookupCb; +// Callback used by the decoder to query shader debug information for mapping shader +// addresses to source or intermediate assembly line. +// Optional, can be NULL. +// Used when GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO is set in +// decoderFlags. +// +// shaderLookupCb; +// Callback used by the decoder to query shader information for mapping shader +// addresses to shader intermediate assembly (DXIL/SPIR-V) or source. +// Optional, can be NULL. +// Used when GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO is set in +// decoderFlags. +// +// shaderInstructionsLookupCb; +// Callback used by the decoder to query shader information for mapping shader +// addresses to shader intermediate assembly (DXIL/SPIR-V) or source. +// Optional, can be NULL. +// Used when GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO is set in +// decoderFlags. +// +// shaderSourceDebugInfoLookupCb; +// Callback used by the decoder to query high-level shader debug information for +// mapping shader addresses to shader source, if the shaders used by the application +// are stripped off debug information. This lookup is done by the shader's DebugName, +// a unique identifier of the source debug information. +// +// Optional, can be NULL. +// Used when GFSDK_Aftermath_GpuCrashDumpDecoderFlags_SHADER_MAPPING_INFO is set in +// decoderFlags. +// +// For DXIL shaders DebugName is generated by the dxc compiler and is defined here: +// https://github.com/microsoft/DirectXShaderCompiler/blob/master/docs/SourceLevelDebuggingHLSL.rst#using-debug-names. +// +// The following variants of generating source shader debug information for DXIL shaders +// are supported: +// +// 1) Compile and use a full shader blob +// Compile the shaders with the debug information. Use the full (i.e. not +// stripped) shader binary when running the application and make it accessible +// through shaderLookupCb and shaderInstructionsLookupCb. In this case there is +// no need to provide shaderSourceDebugInfoLookupCb. +// +// Compilation example: +// dxc -Zi [..] -Fo shader.bin shader.hlsl +// +// 2) Compile and strip +// Compile the shaders with debug information and then strip off the debug +// information. Use the stripped shader binary data when running the application. +// Make the stripped shader binary data accessible through shaderLookupCb and +// shaderInstructionsLookupCb. In addition, make the non-stripped shader binary +// data accessible through shaderSourceDebugInfoLookupCb. +// +// Compilation example: +// dxc -Zi [..] -Fo full_shader.bin shader.hlsl +// dxc -dumpbin -Qstrip_debug -Fo shader.bin full_shader.bin +// +// The shader's DebugName required for implementing the +// shaderSourceDebugInfoLookupCb may be extracted from the stripped or the +// non-stripped shader binary data with GFSDK_Aftermath_GetShaderDebugName(). +// +// 3) Compile with separate debug information (and auto-generated debug data file name) +// Compile the shaders with debug information and instruct the compiler to store +// the debug meta data in a separate shader debug information file. The name of +// the file generated by the compiler will match the DebugName of the shader. +// Make the shader binary data accessible through shaderLookupCb and +// shaderInstructionsLookupCb. In addition, make the data from the compiler +// generated shader debug data file accessible through +// shaderSourceDebugInfoLookupCb. +// +// Compilation example: +// dxc -Zi [..] -Fo shader.bin -Fd debugInfo\ shader.hlsl +// +// The debug data file generated by the compiler does not contain any reference to +// the shader's DebugName. It is the responsibility of the user providing the +// shaderSourceDebugInfoLookupCb callback to implement a solution to lookup the +// debug data based on the name of the generated debug data file. +// +// 4) Compile with separate debug information (and user-defined debug data file name) +// Compile the shaders with debug information and instruct the compiler to store +// the debug meta data in a separate shader debug information file. The name of +// the file is freely choosen by the user. Make the shader binary data accessible +// through shaderLookupCb and shaderInstructionsLookupCb. In addition, make the +// data from the compiler generated shader debug data file accessible through +// shaderSourceDebugInfoLookupCb. +// +// Compilation example: +// dxc -Zi [..] -Fo shader.bin -Fd debugInfo\shader.dbg shader.hlsl +// +// The debug data file generated by the compiler does not contain any reference to +// the shader's DebugName. It is the responsibility of the user providing the +// shaderSourceDebugInfoLookupCb callback to implement a solution that performs +// the lookup of the debug data based on a mapping between the shader's DebugName +// the debug data file's name that was chosen for the compilation. The shader's +// DebugName may be extracted from the shader binary data with +// GFSDK_Aftermath_GetShaderDebugName(). +// +// For SPIR-V shaders the Aftermath SDK provides support for the following variants of +// generating source shader debug information: +// +// 1) Compile and use a full shader blob +// Compile the shaders with the debug information. Use the full (i.e. not +// stripped) shader binary when running the application and make it accessible +// through shaderLookupCb. In this case there is no need to provide +// shaderInstructionsLookupCb or shaderSourceDebugInfoLookupCb. +// +// Compilation example using Vulkan SDK tool-chain: +// glslangValidator -V -g -o ./full/shader.spv shader.vert +// +// 2) Compile and strip +// Compile the shaders with debug information and then strip off the debug +// information. Use the stripped shader binary data when running the application. +// Make the stripped shader binary data accessible through shaderLookupCb. +// In addition, make the non-stripped shader binary data accessible through +// shaderSourceDebugInfoLookupCb. +// +// Compilation example using Vulkan SDK tool-chain: +// glslangValidator -V -g -o ./full/shader.spv shader.vert +// spirv-remap --map all --strip-all --input full/shader.spv --output ./stripped/ +// +// Then pass the content of ./full/shader.spv and ./stripped/shader.spv to +// GFSDK_Aftermath_GetDebugNameSpirv() to generate the debug name to use with +// shaderSourceDebugInfoLookupCb. +// +// pUserData; +// User data made available in callbacks. +// +// pJsonSize; +// Populated with the size of the generated JSON data in bytes. +// +//// DESCRIPTION; +// Decode a crash dump to JSON format. +// The decoded JSON can be later queried by calling GFSDK_Aftermath_GpuCrashDump_GetJSON. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GenerateJSON( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + uint32_t decoderFlags, + uint32_t formatFlags, + PFN_GFSDK_Aftermath_ShaderDebugInfoLookupCb shaderDebugInfoLookupCb, + PFN_GFSDK_Aftermath_ShaderLookupCb shaderLookupCb, + PFN_GFSDK_Aftermath_ShaderInstructionsLookupCb shaderInstructionsLookupCb, + PFN_GFSDK_Aftermath_ShaderSourceDebugInfoLookupCb shaderSourceDebugInfoLookupCb, + void* pUserData, + uint32_t* pJsonSize); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GpuCrashDump_GetJSON +// --------------------------------- +// +// decoder; +// A valid decoder object. +// +// jsonBufferSize; +// The size of the caller allocated buffer for the JSON data in bytes. +// +// pJson; +// Caller allocated buffer populated with the JSON data (0-terminated string). +// +//// DESCRIPTION; +// Copy the JSON generated by the last call to GFSDK_Aftermath_GpuCrashDump_GenerateJSON +// into a caller provided buffer. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GpuCrashDump_GetJSON( + const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, + const uint32_t jsonBufferSize, + char* pJson); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetShaderDebugInfoIdentifier +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pShaderDebugInfo; +// Pointer to shader debug information data captured in a GFSDK_Aftermath_ShaderDebugInfoCb callback. +// +// shaderDebugInfoSize; +// Size in bytes of the shader debug information data. +// +// pIdentifier; +// Pointer to GFSDK_Aftermath_ShaderDebugInfoIdentifier structure receiving the result +// +//// DESCRIPTION; +// Read the shader debug information identifier from shader debug information. +// The shader debug information identifier is required when implementing the +// PFN_GFSDK_Aftermath_ShaderDebugInfoLookupCb callback. +// +///////////////////////////////////////////////////////////////////////// +GFSDK_Aftermath_API GFSDK_Aftermath_GetShaderDebugInfoIdentifier( + GFSDK_Aftermath_Version apiVersion, + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize, + GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier); + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetShaderHash +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pShader; +// The binary shader blob for which to compute the identifier. +// +// pShaderHash; +// Pointer to GFSDK_Aftermath_ShaderHash structure receiving the computed shader hash. +// Optional, can be NULL. +// +// pShaderInstructionsHash; +// Pointer to GFSDK_Aftermath_ShaderInstructionsHash structure receiving the computed +// shader instructions hash. +// Optional, can be NULL. +// +//// DESCRIPTION; +// Computes shader hashes uniquely identifying the provided DXBC shader binary. +// This is, for example, required for comparison in the shader binary lookup by +// PFN_GFSDK_Aftermath_ShaderLookupCb or PFN_GFSDK_Aftermath_ShaderInstructionsLookupCb. +// +///////////////////////////////////////////////////////////////////////// +#if defined(__d3d12_h__) +GFSDK_Aftermath_API GFSDK_Aftermath_GetShaderHash( + GFSDK_Aftermath_Version apiVersion, + const D3D12_SHADER_BYTECODE* pShader, + GFSDK_Aftermath_ShaderHash* pShaderHash, + GFSDK_Aftermath_ShaderInstructionsHash* pShaderInstructionsHash); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetShaderHashSpirv +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pShader; +// The SPIR-V shader binary for which to compute the identifier. +// +// pShaderHash; +// Pointer to GFSDK_Aftermath_ShaderHash structure receiving the computed shader hash. +// Optional, can be NULL. +// +//// DESCRIPTION; +// Computes a shader hash uniquely identifying the provided SPIR-V shader binary. +// This is, for example, required for comparison in the shader binary lookup by +// PFN_GFSDK_Aftermath_ShaderLookupCb. +// +///////////////////////////////////////////////////////////////////////// +#if defined(VULKAN_H_) +GFSDK_Aftermath_API GFSDK_Aftermath_GetShaderHashSpirv( + GFSDK_Aftermath_Version apiVersion, + const GFSDK_Aftermath_SpirvCode *pShader, + GFSDK_Aftermath_ShaderHash* pShaderHash); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetShaderDebugName +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pShader; +// The binary shader data blob from which to extract the DebugName. +// +// pShaderDebugName; +// Pointer to GFSDK_Aftermath_ShaderDebugName structure receiving the DebugName. +// +//// DESCRIPTION; +// Extracts the shader's DebugName (if available) from the provided DXBC shader binary. +// This is, for example, required for comparison in the shader debug data lookup by +// PFN_GFSDK_Aftermath_ShaderSourceDebugInfoLookupCb. For more information about shader +// debug names please read: +// https://github.com/microsoft/DirectXShaderCompiler/blob/master/docs/SourceLevelDebuggingHLSL.rst#using-debug-names. +// +///////////////////////////////////////////////////////////////////////// +#if defined(__d3d12_h__) +GFSDK_Aftermath_API GFSDK_Aftermath_GetShaderDebugName( + GFSDK_Aftermath_Version apiVersion, + const D3D12_SHADER_BYTECODE* pShader, + GFSDK_Aftermath_ShaderDebugName* pShaderDebugName); +#endif + +///////////////////////////////////////////////////////////////////////// +// GFSDK_Aftermath_GetShaderDebugNameSpirv +// --------------------------------- +// +// apiVersion; +// Must be set to GFSDK_Aftermath_Version_API. Used for checking against library +// version. +// +// pShader; +// The not-stripped SPIR-V binary shader data of the shader pair for which to +// generate the DebugName. +// +// pStrippedShader; +// The stripped SPIR-V binary shader data of the shader pair for which to +// generate the DebugName. +// +// pShaderDebugName; +// Pointer to GFSDK_Aftermath_ShaderDebugName structure receiving the DebugName. +// +//// DESCRIPTION; +// Generates a shader DebugName from the provided pair of SPIR-V shader binary +// data. This is, for example, required for comparison in the shader debug data +// lookup by PFN_GFSDK_Aftermath_ShaderSourceDebugInfoLookupCb. For more information +// about how to generate the pair of shader binaries, see the description of +// GFSDK_Aftermath_GpuCrashDump_GenerateJSON(). +// +///////////////////////////////////////////////////////////////////////// +#if defined(VULKAN_H_) +GFSDK_Aftermath_API GFSDK_Aftermath_GetShaderDebugNameSpirv( + GFSDK_Aftermath_Version apiVersion, + const GFSDK_Aftermath_SpirvCode *pShader, + const GFSDK_Aftermath_SpirvCode *pStrippedShader, + GFSDK_Aftermath_ShaderDebugName* pShaderDebugName); +#endif + +///////////////////////////////////////////////////////////////////////// +// +// NOTE: Function table provided - if dynamic loading is preferred. +// +///////////////////////////////////////////////////////////////////////// + +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_CreateDecoder)(GFSDK_Aftermath_Version apiVersion, const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize, GFSDK_Aftermath_GpuCrashDump_Decoder* pDecoder); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_DestroyDecoder)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetBaseInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, GFSDK_Aftermath_GpuCrashDump_BaseInfo* pBaseInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t key, uint32_t* pValueSize); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetDescription)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t key, const uint32_t valueBufferSize, char* pValue); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetDeviceInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, GFSDK_Aftermath_GpuCrashDump_DeviceInfo* pDeviceInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetSystemInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, GFSDK_Aftermath_GpuCrashDump_SystemInfo* pSystemInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetGpuInfoCount)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, uint32_t* pGpuCount); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetGpuInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t gpuInfoBufferCount, GFSDK_Aftermath_GpuCrashDump_GpuInfo* pGpuInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetPageFaultInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, GFSDK_Aftermath_GpuCrashDump_PageFaultInfo* pPageFaultInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfoCount)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, uint32_t* pShaderCount); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetActiveShadersInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t shaderInfoBufferCount, GFSDK_Aftermath_GpuCrashDump_ShaderInfo* pShaderInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfoCount)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t markerInfoBufferCount); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetEventMarkersInfo)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t markerInfoBufferCount, GFSDK_Aftermath_GpuCrashDump_EventMarkerInfo* pMarkerInfo); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GenerateJSON)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, uint32_t decoderFlags, uint32_t formatFlags, PFN_GFSDK_Aftermath_ShaderDebugInfoLookupCb shaderDebugInfoLookupCb, PFN_GFSDK_Aftermath_ShaderLookupCb shaderLookupCb, PFN_GFSDK_Aftermath_ShaderInstructionsLookupCb shaderInstructionsLookupCb, PFN_GFSDK_Aftermath_ShaderSourceDebugInfoLookupCb shaderSourceDebugInfoLookupCb, void* pUserData, uint32_t* pJsonSize); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GpuCrashDump_GetJSON)(const GFSDK_Aftermath_GpuCrashDump_Decoder decoder, const uint32_t jsonBufferSize, char* pJson); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetShaderDebugInfoIdentifier)(GFSDK_Aftermath_Version apiVersion, const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize, GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier); +#if defined(__d3d12_h__) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetShaderHash)(GFSDK_Aftermath_Version apiVersion, const D3D12_SHADER_BYTECODE* pShader, GFSDK_Aftermath_ShaderHash* pShaderHash, GFSDK_Aftermath_ShaderInstructionsHash* pShaderInstructionsHash); +GFSDK_Aftermath_PFN(*GPFN_GFSDK_Aftermath_GetShaderDebugName)(GFSDK_Aftermath_Version apiVersion, const D3D12_SHADER_BYTECODE* pShader, GFSDK_Aftermath_ShaderDebugName* pShaderDebugName); +#endif +#if defined(VULKAN_H_) +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetShaderHashSpirv)(GFSDK_Aftermath_Version apiVersion, const GFSDK_Aftermath_SpirvCode *pShader, GFSDK_Aftermath_ShaderHash* pShaderHash); +GFSDK_Aftermath_PFN(GFSDK_AFTERMATH_CALL *PFN_GFSDK_Aftermath_GetShaderDebugNameSpirv)(GFSDK_Aftermath_Version apiVersion, const GFSDK_Aftermath_SpirvCode *pShader, const GFSDK_Aftermath_SpirvCode *pStrippedShader, GFSDK_Aftermath_ShaderDebugName* pShaderDebugName); +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#pragma pack(pop) + +#endif // GFSDK_Aftermath_CrashDumpDecoding_H + diff --git a/external/aftermath/nsight-aftermath-usage-guidelines.txt b/external/aftermath/nsight-aftermath-usage-guidelines.txt new file mode 100644 index 0000000..77dc5f3 --- /dev/null +++ b/external/aftermath/nsight-aftermath-usage-guidelines.txt @@ -0,0 +1,22 @@ +Nsight Aftermath is primarily a development tool and is intended to be used +with minimal side effects to the user application. Despite this, there may be +overhead when it is enabled resulting in performance degradation. The +application should only fully enable Nsight Aftermath when in an application +controlled 'diagnostics mode', e.g. enabled after the user has experienced a +GPU crash and exhaustive data collection is required. + +Your users should also be able to easily disable Nsight Aftermath in situations +where performance is critical, such as when benchmarking or during competitive +play. + +To override the behavior of applications that do not follow the above guidelines +a user may force off all Aftermath functionality in the application: + +on Windows, set a Windows registry key: +HKEY_CURRENT_USER\Software\NVIDIA Corporation\Nsight Aftermath\ForceOff=1 + +on Linux, set an environment variable: +export NV_AFTERMATH_FORCE_OFF=1 + +For questions regarding these guidelines or Nsight Aftermath in general, please +email NsightAftermath@nvidia.com diff --git a/res/shaders/ForwardPlus.slang b/res/shaders/ForwardPlus.slang index e5f64fb..1cdace4 100644 --- a/res/shaders/ForwardPlus.slang +++ b/res/shaders/ForwardPlus.slang @@ -56,22 +56,21 @@ float4 fragmentMain( float3 result = float3(0, 0, 0); - for (int i = 0; i < gLightEnv[0].numDirectionalLights; i++) + for (int i = 0; i < gLightEnv.numDirectionalLights; i++) { - result += gLightEnv[0].directionalLights[i].illuminate(materialParams, brdf, viewDir); + result += gLightEnv.directionalLights[i].illuminate(materialParams, brdf, viewDir); } - uint2 tileIndex = uint2(floor(materialParams.clipPosition.xy) / BLOCK_SIZE); + uint2 tileIndex = uint2(floor(position.xy / BLOCK_SIZE)); + uint2 gridValue = lightGrid[tileIndex]; + uint startOffset = gridValue.x; + uint lightCount = gridValue.y; - uint startOffset = lightGrid[tileIndex].x; - uint lightCount = lightGrid[tileIndex].y; - - for (int j = 0; j < gLightEnv[0].numPointLights; ++j) + for (int j = 0; j < lightCount; ++j) { uint lightIndex = lightIndexList[startOffset + j]; - PointLight pointLight = gLightEnv[0].pointLights[lightIndex]; + PointLight pointLight = gLightEnv.pointLights[lightIndex]; result += pointLight.illuminate(materialParams, brdf, viewDir); } - - return float4(result, 0); + return float4(result, 1); } diff --git a/res/shaders/LightCulling.slang b/res/shaders/LightCulling.slang index 3fb866c..0f1c9c9 100644 --- a/res/shaders/LightCulling.slang +++ b/res/shaders/LightCulling.slang @@ -102,16 +102,11 @@ void cullLights(ComputeShaderInput in) Plane minPlane = {float3(0, 0, -1), -minDepthVS}; - for ( uint i = in.groupIndex; i < gLightEnv[0].numPointLights; i += BLOCK_SIZE * BLOCK_SIZE ) + for ( uint i = in.groupIndex; i < gLightEnv.numPointLights; i += BLOCK_SIZE * BLOCK_SIZE ) { - PointLight light = gLightEnv[0].pointLights[i]; + PointLight light = gLightEnv.pointLights[i]; //if(gLightEnv.insideFrustum(groupFrustum, nearClipVS, maxDepthVS)) { - //InterlockedAdd(tLightCount, 1, index); - //if(index < 1024) - //{ - // tLightList[index] = i; - //} //if(!light.insidePlane(minPlane)) //{ oAppendLight(i); @@ -131,15 +126,11 @@ void cullLights(ComputeShaderInput in) } GroupMemoryBarrierWithGroupSync(); - if(in.groupIndex == 0) - { - for (uint j = 0; j < (uint)oLightCount; j += 1/*BLOCK_SIZE * BLOCK_SIZE*/) - { - oLightIndexList[oLightIndexStartOffset + j] = oLightList[j]; - } - } + for (uint j = in.groupIndex; j < (uint)oLightCount; j += BLOCK_SIZE * BLOCK_SIZE) + { + oLightIndexList[oLightIndexStartOffset + j] = oLightList[j]; + } - // For transparent geometry. for ( uint k = in.groupIndex; k < (uint)tLightCount; k += BLOCK_SIZE * BLOCK_SIZE ) { diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index c2cef05..3fda9fe 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -7,8 +7,8 @@ struct ViewParameter float4x4 viewMatrix; float4x4 projectionMatrix; float4x4 inverseProjection; - float2 screenDimensions; float4 cameraPos_WS; + float2 screenDimensions; } layout(set = INDEX_VIEW_PARAMS, binding = 0, std430) ConstantBuffer gViewParams; diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 9384a88..757e553 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -69,4 +69,4 @@ struct Lights }; layout(set = INDEX_LIGHT_ENV, binding = 0, std430) -StructuredBuffer gLightEnv; +ConstantBuffer gLightEnv; diff --git a/src/Engine/Graphics/GraphicsEnums.h b/src/Engine/Graphics/GraphicsEnums.h index 592f004..096f48a 100644 --- a/src/Engine/Graphics/GraphicsEnums.h +++ b/src/Engine/Graphics/GraphicsEnums.h @@ -162,7 +162,7 @@ typedef uint32 KeyModifierFlags; namespace Gfx { static constexpr bool useAsyncCompute = true; -static constexpr bool waitIdleOnSubmit = false; +static constexpr bool waitIdleOnSubmit = true; static constexpr uint32 numFramesBuffered = 8; extern uint32 currentFrameIndex; extern double currentFrameDelta; diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index 9f52931..c03eaac 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -212,13 +212,25 @@ bool UniformBuffer::updateContents(const BulkResourceData& resourceData) return true; } -StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType) - : Buffer(mapping, startQueueType) +StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, const BulkResourceData& resourceData) + : Buffer(mapping, resourceData.owner) + , contents(resourceData.size) { } StructuredBuffer::~StructuredBuffer() { } + +bool StructuredBuffer::updateContents(const BulkResourceData& resourceData) +{ + assert(contents.size() == resourceData.size); + if(std::memcmp(contents.data(), resourceData.data, contents.size()) == 0) + { + return false; + } + std::memcpy(contents.data(), resourceData.data, contents.size()); + return true; +} VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType) : Buffer(mapping, startQueueType) , numVertices(numVertices) diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index 344cc6f..b6199e9 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -405,9 +405,27 @@ DEFINE_REF(IndexBuffer) class StructuredBuffer : public Buffer { public: - StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType); + StructuredBuffer(QueueFamilyMapping mapping, const BulkResourceData& bulkResourceData); virtual ~StructuredBuffer(); + virtual bool updateContents(const BulkResourceData& resourceData); + bool isDataEquals(StructuredBuffer* other) + { + if(other == nullptr) + { + return false; + } + if(contents.size() != other->contents.size()) + { + return false; + } + if(std::memcmp(contents.data(), other->contents.data(), contents.size()) != 0) + { + return false; + } + return true; + } protected: + Array contents; // Inherited via QueueOwnedResource virtual void executeOwnershipBarrier(QueueType newOwner) = 0; virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage, diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index ad52e46..54a9353 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -92,7 +92,7 @@ BasePass::BasePass(PRenderGraph renderGraph, const PScene scene, Gfx::PGraphics basePassLayout = graphics->createPipelineLayout(); lightLayout = graphics->createDescriptorLayout("LightLayout"); - lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + lightLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); lightLayout->addDescriptorBinding(1, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); lightLayout->addDescriptorBinding(2, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE); lightLayout->create(); @@ -133,6 +133,10 @@ void BasePass::beginFrame() uniformUpdate.size = sizeof(ViewParameter); uniformUpdate.data = (uint8*)&viewParams; viewParamBuffer->updateContents(uniformUpdate); + viewLayout->reset(); + lightLayout->reset(); + descriptorSets[INDEX_LIGHT_ENV] = lightLayout->allocateDescriptorSet(); + descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); for(auto &&meshBatch : scene->getStaticMeshes()) @@ -143,7 +147,6 @@ void BasePass::beginFrame() void BasePass::render() { - descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, scene->getLightBuffer()); oLightIndexList->pipelineBarrier( Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, @@ -151,6 +154,8 @@ void BasePass::render() oLightGrid->pipelineBarrier( Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(0, scene->getLightBuffer()); descriptorSets[INDEX_LIGHT_ENV]->updateBuffer(1, oLightIndexList); descriptorSets[INDEX_LIGHT_ENV]->updateTexture(2, oLightGrid); descriptorSets[INDEX_LIGHT_ENV]->writeChanges(); diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 7e2bb5a..d467f35 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -99,7 +99,6 @@ DepthPrepass::DepthPrepass(PRenderGraph renderGraph, const PScene scene, Gfx::PG viewParamBuffer = graphics->createUniformBuffer(uniformInitializer); viewLayout->create(); depthPrepassLayout->addDescriptorLayout(INDEX_VIEW_PARAMS, viewLayout); - descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); primitiveLayout = graphics->createDescriptorLayout("PrimitiveLayout"); primitiveLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); @@ -125,6 +124,8 @@ void DepthPrepass::beginFrame() uniformUpdate.size = sizeof(ViewParameter); uniformUpdate.data = (uint8*)&viewParams; viewParamBuffer->updateContents(uniformUpdate); + viewLayout->reset(); + descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); for(auto &&meshBatch : scene->getStaticMeshes()) diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 283fe4a..6023f26 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -23,20 +23,32 @@ LightCullingPass::~LightCullingPass() void LightCullingPass::beginFrame() { + uint32_t viewportWidth = viewport->getSizeX(); + uint32_t viewportHeight = viewport->getSizeY(); + BulkResourceData uniformUpdate; viewParams.viewMatrix = source->getViewMatrix(); viewParams.projectionMatrix = source->getProjectionMatrix(); viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0); viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix); - viewParams.screenDimensions = Vector2(static_cast(viewport->getSizeX()), static_cast(viewport->getSizeY())); + viewParams.screenDimensions = Vector2(static_cast(viewportWidth), static_cast(viewportHeight)); uniformUpdate.size = sizeof(ViewParameter); uniformUpdate.data = (uint8*)&viewParams; viewParamsBuffer->updateContents(uniformUpdate); + + BulkResourceData counterReset; + uint32 reset = 0; + counterReset.data = (uint8*)&reset; + counterReset.size = sizeof(uint32); + oLightIndexCounter->updateContents(counterReset); + tLightIndexCounter->updateContents(counterReset); + cullingDescriptorLayout->reset(); lightEnvDescriptorLayout->reset(); cullingDescriptorSet = cullingDescriptorLayout->allocateDescriptorSet(); lightEnvDescriptorSet = lightEnvDescriptorLayout->allocateDescriptorSet(); + cullingDescriptorSet->updateBuffer(0, viewParamsBuffer); cullingDescriptorSet->updateBuffer(1, dispatchParamsBuffer); cullingDescriptorSet->updateBuffer(3, frustumBuffer); @@ -61,7 +73,6 @@ void LightCullingPass::render() Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL); depthAttachment->transferOwnership(Gfx::QueueType::COMPUTE); - cullingDescriptorSet->updateTexture(2, depthAttachment); cullingDescriptorSet->writeChanges(); lightEnvDescriptorSet->updateBuffer(0, scene->getLightBuffer()); @@ -85,16 +96,29 @@ void LightCullingPass::endFrame() void LightCullingPass::publishOutputs() { setupFrustums(); + uint32_t viewportWidth = viewport->getSizeX(); + uint32_t viewportHeight = viewport->getSizeY(); + glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1)); + dispatchParams.numThreadGroups = numThreadGroups; + dispatchParams.numThreads = numThreadGroups * glm::uvec3(BLOCK_SIZE, BLOCK_SIZE, 1); + BulkResourceData resourceData; StructuredBufferCreateInfo createInfo; + uint32 counterReset = 0; resourceData.size = sizeof(uint32); - resourceData.data = nullptr; + resourceData.data = (uint8*)&counterReset; resourceData.owner = Gfx::QueueType::COMPUTE; - createInfo.bDynamic = false; + createInfo.bDynamic = true; createInfo.resourceData = resourceData; oLightIndexCounter = graphics->createStructuredBuffer(createInfo); tLightIndexCounter = graphics->createStructuredBuffer(createInfo); - resourceData.size = sizeof(uint32_t) * dispatchParams.numThreadGroups.x * dispatchParams.numThreadGroups.y * dispatchParams.numThreadGroups.z * 1024; + resourceData.data = nullptr; + resourceData.size = sizeof(uint32_t) + * dispatchParams.numThreadGroups.x + * dispatchParams.numThreadGroups.y + * dispatchParams.numThreadGroups.z * 200; + createInfo.resourceData = resourceData; + createInfo.bDynamic = false; oLightIndexList = graphics->createStructuredBuffer(createInfo); tLightIndexList = graphics->createStructuredBuffer(createInfo); renderGraph->registerBufferOutput("LIGHTCULLING_OLIGHTLIST", oLightIndexList); @@ -102,7 +126,7 @@ void LightCullingPass::publishOutputs() TextureCreateInfo textureInfo; textureInfo.width = dispatchParams.numThreadGroups.x; textureInfo.height = dispatchParams.numThreadGroups.y; - textureInfo.format = Gfx::SE_FORMAT_R16G16_UINT; + textureInfo.format = Gfx::SE_FORMAT_R32G32_UINT; textureInfo.usage = Gfx::SE_IMAGE_USAGE_STORAGE_BIT; oLightGrid = graphics->createTexture2D(textureInfo); tLightGrid = graphics->createTexture2D(textureInfo); @@ -139,7 +163,7 @@ void LightCullingPass::createRenderPass() lightEnvDescriptorLayout = graphics->createDescriptorLayout("LightEnv"); //LightEnv - lightEnvDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER); + lightEnvDescriptorLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER); cullingLayout = graphics->createPipelineLayout(); cullingLayout->addDescriptorLayout(0, cullingDescriptorLayout); @@ -251,5 +275,6 @@ void LightCullingPass::setupFrustums() command->dispatch(numThreadGroups.x, numThreadGroups.y, numThreadGroups.z); Array commands = {command}; graphics->executeCommands(commands); - frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT); } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/RenderPass.h b/src/Engine/Graphics/RenderPass/RenderPass.h index 738360b..385df76 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.h +++ b/src/Engine/Graphics/RenderPass/RenderPass.h @@ -17,13 +17,13 @@ public: virtual void publishOutputs() = 0; virtual void createRenderPass() = 0; protected: - struct ViewParameter + _declspec(align(16)) struct ViewParameter { Matrix4 viewMatrix; Matrix4 projectionMatrix; Matrix4 inverseProjectionMatrix; - Vector2 screenDimensions; Vector4 cameraPosition; + Vector2 screenDimensions; } viewParams; Gfx::PRenderPass renderPass; PRenderGraph renderGraph; diff --git a/src/Engine/Graphics/Vulkan/CMakeLists.txt b/src/Engine/Graphics/Vulkan/CMakeLists.txt index cbe8ba1..c151a8b 100644 --- a/src/Engine/Graphics/Vulkan/CMakeLists.txt +++ b/src/Engine/Graphics/Vulkan/CMakeLists.txt @@ -1,5 +1,10 @@ target_sources(SeeleEngine PRIVATE + NsightAftermathGpuCrashTracker.h + NsightAftermathGpuCrashTracker.cpp + NsightAftermathHelpers.h + NsightAftermathShaderDatabase.h + NsightAftermathShaderDatabase.cpp VulkanAllocator.h VulkanAllocator.cpp VulkanBuffer.cpp diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp new file mode 100644 index 0000000..7eb32e4 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp @@ -0,0 +1,346 @@ +//********************************************************* +// +// Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* + +#include +#include +#include + +#include "NsightAftermathGpuCrashTracker.h" + +//********************************************************* +// GpuCrashTracker implementation +//********************************************************* + +GpuCrashTracker::GpuCrashTracker() + : m_initialized(false) + , m_mutex() + , m_shaderDebugInfo() + , m_shaderDatabase() +{ +} + +GpuCrashTracker::~GpuCrashTracker() +{ + // If initialized, disable GPU crash dumps + if (m_initialized) + { + GFSDK_Aftermath_DisableGpuCrashDumps(); + } +} + +// Initialize the GPU Crash Dump Tracker +void GpuCrashTracker::Initialize() +{ + // Enable GPU crash dumps and set up the callbacks for crash dump notifications, + // shader debug information notifications, and providing additional crash + // dump description data.Only the crash dump callback is mandatory. The other two + // callbacks are optional and can be omitted, by passing nullptr, if the corresponding + // functionality is not used. + // The DeferDebugInfoCallbacks flag enables caching of shader debug information data + // in memory. If the flag is set, ShaderDebugInfoCallback will be called only + // in the event of a crash, right before GpuCrashDumpCallback. If the flag is not set, + // ShaderDebugInfoCallback will be called for every shader that is compiled. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_EnableGpuCrashDumps( + GFSDK_Aftermath_Version_API, + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan, + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks, // Let the Nsight Aftermath library cache shader debug information. + GpuCrashDumpCallback, // Register callback for GPU crash dumps. + ShaderDebugInfoCallback, // Register callback for shader debug information. + CrashDumpDescriptionCallback, // Register callback for GPU crash dump description. + this)); // Set the GpuCrashTracker object as user data for the above callbacks. + + m_initialized = true; +} + +// Handler for GPU crash dump callbacks from Nsight Aftermath +void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) +{ + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Write to file for later in-depth analysis with Nsight Graphics. + WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); +} + +// Handler for shader debug information callbacks +void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) +{ + // Make sure only one thread at a time... + std::lock_guard lock(m_mutex); + + // Get shader debug information identifier + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugInfoIdentifier( + GFSDK_Aftermath_Version_API, + pShaderDebugInfo, + shaderDebugInfoSize, + &identifier)); + + // Store information for decoding of GPU crash dumps with shader address mapping + // from within the application. + std::vector data((uint8_t*)pShaderDebugInfo, (uint8_t*)pShaderDebugInfo + shaderDebugInfoSize); + m_shaderDebugInfo[identifier].swap(data); + + // Write to file for later in-depth analysis of crash dumps with Nsight Graphics + WriteShaderDebugInformationToFile(identifier, pShaderDebugInfo, shaderDebugInfoSize); +} + +// Handler for GPU crash dump description callbacks +void GpuCrashTracker::OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription) +{ + // Add some basic description about the crash. This is called after the GPU crash happens, but before + // the actual GPU crash dump callback. The provided data is included in the crash dump and can be + // retrieved using GFSDK_Aftermath_GpuCrashDump_GetDescription(). + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "VkHelloNsightAftermath"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationVersion, "v1.0"); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined, "This is a GPU crash dump example."); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 1, "Engine State: Rendering."); + addDescription(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_UserDefined + 2, "More user-defined information..."); +} + +// Helper for writing a GPU crash dump to a file +void GpuCrashTracker::WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) +{ + // Create a GPU crash dump decoder object for the GPU crash dump. + GFSDK_Aftermath_GpuCrashDump_Decoder decoder = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_CreateDecoder( + GFSDK_Aftermath_Version_API, + pGpuCrashDump, + gpuCrashDumpSize, + &decoder)); + + // Use the decoder object to read basic information, like application + // name, PID, etc. from the GPU crash dump. + GFSDK_Aftermath_GpuCrashDump_BaseInfo baseInfo = {}; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetBaseInfo(decoder, &baseInfo)); + + // Use the decoder object to query the application name that was set + // in the GPU crash dump description. + uint32_t applicationNameLength = 0; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescriptionSize( + decoder, + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, + &applicationNameLength)); + + std::vector applicationName(applicationNameLength, '\0'); + + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetDescription( + decoder, + GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, + uint32_t(applicationName.size()), + applicationName.data())); + + // Create a unique file name for writing the crash dump data to a file. + // Note: due to an Nsight Aftermath bug (will be fixed in an upcoming + // driver release) we may see redundant crash dumps. As a workaround, + // attach a unique count to each generated file name. + static int count = 0; + const std::string baseFileName = + std::string(applicationName.data()) + + "-" + + std::to_string(baseInfo.pid) + + "-" + + std::to_string(++count); + + // Write the the crash dump data to a file using the .nv-gpudmp extension + // registered with Nsight Graphics. + const std::string crashDumpFileName = baseFileName + ".nv-gpudmp"; + std::ofstream dumpFile(crashDumpFileName, std::ios::out | std::ios::binary); + if (dumpFile) + { + dumpFile.write((const char*)pGpuCrashDump, gpuCrashDumpSize); + dumpFile.close(); + } + + // Decode the crash dump to a JSON string. + // Step 1: Generate the JSON and get the size. + uint32_t jsonSize = 0; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GenerateJSON( + decoder, + GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO, + GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE, + ShaderDebugInfoLookupCallback, + ShaderLookupCallback, + nullptr, + ShaderSourceDebugInfoLookupCallback, + this, + &jsonSize)); + // Step 2: Allocate a buffer and fetch the generated JSON. + std::vector json(jsonSize); + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_GetJSON( + decoder, + uint32_t(json.size()), + json.data())); + + // Write the the crash dump data as JSON to a file. + const std::string jsonFileName = crashDumpFileName + ".json"; + std::ofstream jsonFile(jsonFileName, std::ios::out | std::ios::binary); + if (jsonFile) + { + jsonFile.write(json.data(), json.size()); + jsonFile.close(); + } + + // Destroy the GPU crash dump decoder object. + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder)); +} + +// Helper for writing shader debug information to a file +void GpuCrashTracker::WriteShaderDebugInformationToFile( + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize) +{ + // Create a unique file name. + const std::string filePath = "shader-" + std::to_string(identifier) + ".nvdbg"; + + std::ofstream f(filePath, std::ios::out | std::ios::binary); + if (f) + { + f.write((const char*)pShaderDebugInfo, shaderDebugInfoSize); + } +} + +// Handler for shader debug information lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction +// addresses to DXIL lines or HLSl source lines. +void GpuCrashTracker::OnShaderDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const +{ + // Search the list of shader debug information blobs received earlier. + auto i_debugInfo = m_shaderDebugInfo.find(identifier); + if (i_debugInfo == m_shaderDebugInfo.end()) + { + // Early exit, nothing found. No need to call setShaderDebugInfo. + return; + } + + // Let the GPU crash dump decoder know about the shader debug information + // that was found. + setShaderDebugInfo(i_debugInfo->second.data(), uint32_t(i_debugInfo->second.size())); +} + +// Handler for shader lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction +// addresses to DXIL lines or HLSL source lines. +// NOTE: If the application loads stripped shader binaries (-Qstrip_debug), +// Aftermath will require access to both the stripped and the not stripped +// shader binaries. +void GpuCrashTracker::OnShaderLookup( + const GFSDK_Aftermath_ShaderHash& shaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const +{ + // Find shader binary data for the shader hash in the shader database. + std::vector shaderBinary; + if (!m_shaderDatabase.FindShaderBinary(shaderHash, shaderBinary)) + { + // Early exit, nothing found. No need to call setShaderBinary. + return; + } + + // Let the GPU crash dump decoder know about the shader data + // that was found. + setShaderBinary(shaderBinary.data(), uint32_t(shaderBinary.size())); +} + +// Handler for shader source debug info lookup callbacks. +// This is used by the JSON decoder for mapping shader instruction addresses to +// HLSL source lines, if the shaders used by the application were compiled with +// separate debug info data files. +void GpuCrashTracker::OnShaderSourceDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const +{ + // Find source debug info for the shader DebugName in the shader database. + std::vector shaderBinary; + if (!m_shaderDatabase.FindShaderBinaryWithDebugData(shaderDebugName, shaderBinary)) + { + // Early exit, nothing found. No need to call setShaderBinary. + return; + } + + // Let the GPU crash dump decoder know about the shader debug data that was + // found. + setShaderBinary(shaderBinary.data(), uint32_t(shaderBinary.size())); +} + +// Static callback wrapper for OnCrashDump +void GpuCrashTracker::GpuCrashDumpCallback( + const void* pGpuCrashDump, + const uint32_t gpuCrashDumpSize, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnCrashDump(pGpuCrashDump, gpuCrashDumpSize); +} + +// Static callback wrapper for OnShaderDebugInfo +void GpuCrashTracker::ShaderDebugInfoCallback( + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize); +} + +// Static callback wrapper for OnDescription +void GpuCrashTracker::CrashDumpDescriptionCallback( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnDescription(addDescription); +} + +// Static callback wrapper for OnShaderDebugInfoLookup +void GpuCrashTracker::ShaderDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderDebugInfoLookup(*pIdentifier, setShaderDebugInfo); +} + +// Static callback wrapper for OnShaderLookup +void GpuCrashTracker::ShaderLookupCallback( + const GFSDK_Aftermath_ShaderHash* pShaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderLookup(*pShaderHash, setShaderBinary); +} + +// Static callback wrapper for OnShaderSourceDebugInfoLookup +void GpuCrashTracker::ShaderSourceDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData) +{ + GpuCrashTracker* pGpuCrashTracker = reinterpret_cast(pUserData); + pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary); +} diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.h b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.h new file mode 100644 index 0000000..289d380 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.h @@ -0,0 +1,159 @@ +//********************************************************* +// +// Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* + +#pragma once + +#include +#include + +#include "NsightAftermathHelpers.h" +#include "NsightAftermathShaderDatabase.h" + +//********************************************************* +// Implements GPU crash dump tracking using the Nsight +// Aftermath API. +// +class GpuCrashTracker +{ +public: + GpuCrashTracker(); + ~GpuCrashTracker(); + + // Initialize the GPU crash dump tracker. + void Initialize(); + +private: + + //********************************************************* + // Callback handlers for GPU crash dumps and related data. + // + + // Handler for GPU crash dump callbacks. + void OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); + + // Handler for shader debug information callbacks. + void OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize); + + // Handler for GPU crash dump description callbacks. + void OnDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription); + + //********************************************************* + // Helpers for writing a GPU crash dump and debug information + // data to files. + // + + // Helper for writing a GPU crash dump to a file. + void WriteGpuCrashDumpToFile(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); + + // Helper for writing shader debug information to a file + void WriteShaderDebugInformationToFile( + GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier, + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize); + + //********************************************************* + // Helpers for decoding GPU crash dump to JSON. + // + + // Handler for shader debug info lookup callbacks. + void OnShaderDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo) const; + + // Handler for shader lookup callbacks. + void OnShaderLookup( + const GFSDK_Aftermath_ShaderHash& shaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const; + + // Handler for shader instructions lookup callbacks. + void OnShaderInstructionsLookup( + const GFSDK_Aftermath_ShaderInstructionsHash& shaderInstructionsHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const; + + // Handler for shader source debug info lookup callbacks. + void OnShaderSourceDebugInfoLookup( + const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary) const; + + //********************************************************* + // Static callback wrappers. + // + + // GPU crash dump callback. + static void GpuCrashDumpCallback( + const void* pGpuCrashDump, + const uint32_t gpuCrashDumpSize, + void* pUserData); + + // Shader debug information callback. + static void ShaderDebugInfoCallback( + const void* pShaderDebugInfo, + const uint32_t shaderDebugInfoSize, + void* pUserData); + + // GPU crash dump description callback. + static void CrashDumpDescriptionCallback( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, + void* pUserData); + + // Shader debug information lookup callback. + static void ShaderDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugInfoIdentifier* pIdentifier, + PFN_GFSDK_Aftermath_SetData setShaderDebugInfo, + void* pUserData); + + // Shader lookup callback. + static void ShaderLookupCallback( + const GFSDK_Aftermath_ShaderHash* pShaderHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData); + + // Shader instructions lookup callback. + static void ShaderInstructionsLookupCallback( + const GFSDK_Aftermath_ShaderInstructionsHash* pShaderInstructionsHash, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData); + + // Shader source debug info lookup callback. + static void ShaderSourceDebugInfoLookupCallback( + const GFSDK_Aftermath_ShaderDebugName* pShaderDebugName, + PFN_GFSDK_Aftermath_SetData setShaderBinary, + void* pUserData); + + //********************************************************* + // GPU crash tracker state. + // + + // Is the GPU crash dump tracker initialized? + bool m_initialized; + + // For thread-safe access of GPU crash tracker state. + mutable std::mutex m_mutex; + + // List of Shader Debug Information by ShaderDebugInfoIdentifier. + std::map> m_shaderDebugInfo; + + // The mock shader database. + ShaderDatabase m_shaderDatabase; +}; diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathHelpers.h b/src/Engine/Graphics/Vulkan/NsightAftermathHelpers.h new file mode 100644 index 0000000..18d7889 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/NsightAftermathHelpers.h @@ -0,0 +1,142 @@ +//********************************************************* +// +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* + +#pragma once + +#include +#include +#include + +#include +#include "GFSDK_Aftermath.h" +#include "GFSDK_Aftermath_GpuCrashDump.h" +#include "GFSDK_Aftermath_GpuCrashDumpDecoding.h" + +//********************************************************* +// Some std::to_string overloads for some Nsight Aftermath +// API types. +// + +namespace std +{ + template + inline std::string to_hex_string(T n) + { + std::stringstream stream; + stream << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex << n; + return stream.str(); + } + + inline std::string to_string(GFSDK_Aftermath_Result result) + { + return std::string("0x") + to_hex_string(static_cast(result)); + } + + inline std::string to_string(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& identifier) + { + return to_hex_string(identifier.id[0]) + "-" + to_hex_string(identifier.id[1]); + } + + inline std::string to_string(const GFSDK_Aftermath_ShaderHash& hash) + { + return to_hex_string(hash.hash); + } + + inline std::string to_string(const GFSDK_Aftermath_ShaderInstructionsHash& hash) + { + return to_hex_string(hash.hash) + "-" + to_hex_string(hash.hash); + } +} // namespace std + +//********************************************************* +// Helper for comparing shader hashes and debug info identifier. +// + +// Helper for comparing GFSDK_Aftermath_ShaderDebugInfoIdentifier. +inline bool operator<(const GFSDK_Aftermath_ShaderDebugInfoIdentifier& lhs, const GFSDK_Aftermath_ShaderDebugInfoIdentifier& rhs) +{ + if (lhs.id[0] == rhs.id[0]) + { + return lhs.id[1] < rhs.id[1]; + } + return lhs.id[0] < rhs.id[0]; +} + +// Helper for comparing GFSDK_Aftermath_ShaderHash. +inline bool operator<(const GFSDK_Aftermath_ShaderHash& lhs, const GFSDK_Aftermath_ShaderHash& rhs) +{ + return lhs.hash < rhs.hash; +} + +// Helper for comparing GFSDK_Aftermath_ShaderInstructionsHash. +inline bool operator<(const GFSDK_Aftermath_ShaderInstructionsHash& lhs, const GFSDK_Aftermath_ShaderInstructionsHash& rhs) +{ + return lhs.hash < rhs.hash; +} + +// Helper for comparing GFSDK_Aftermath_ShaderDebugName. +inline bool operator<(const GFSDK_Aftermath_ShaderDebugName& lhs, const GFSDK_Aftermath_ShaderDebugName& rhs) +{ + return strncmp(lhs.name, rhs.name, sizeof(lhs.name)) < 0; +} + +//********************************************************* +// Helper for checking Nsight Aftermath failures. +// + +inline std::string AftermathErrorMessage(GFSDK_Aftermath_Result result) +{ + switch (result) + { + case GFSDK_Aftermath_Result_FAIL_DriverVersionNotSupported: + return "Unsupported driver version - requires a recent NVIDIA R445 display driver or newer."; + default: + return "Aftermath Error 0x" + std::to_hex_string(result); + } +} + +// Helper macro for checking Nsight Aftermath results and throwing exception +// in case of a failure. +#ifdef _WIN32 +#define AFTERMATH_CHECK_ERROR(FC) \ +[&]() { \ + GFSDK_Aftermath_Result _result = FC; \ + if (!GFSDK_Aftermath_SUCCEED(_result)) \ + { \ + std::cout << AftermathErrorMessage(_result).c_str() << std::endl; \ + exit(1); \ + } \ +}() +#else +#define AFTERMATH_CHECK_ERROR(FC) \ +[&]() { \ + GFSDK_Aftermath_Result _result = FC; \ + if (!GFSDK_Aftermath_SUCCEED(_result)) \ + { \ + printf("%s\n", AftermathErrorMessage(_result).c_str()); \ + fflush(stdout); \ + exit(1); \ + } \ +}() +#endif diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.cpp b/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.cpp new file mode 100644 index 0000000..a93ca30 --- /dev/null +++ b/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.cpp @@ -0,0 +1,147 @@ +//********************************************************* +// +// Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* + +#include +#include + +#include "NsightAftermathShaderDatabase.h" + +//********************************************************* +// ShaderDatabase implementation +//********************************************************* + +ShaderDatabase::ShaderDatabase() + : m_shaderBinaries() + , m_shaderBinariesWithDebugInfo() +{ + // Add shader binaries to database + AddShaderBinary("cube.vert.spirv"); + AddShaderBinary("cube.frag.spirv"); + + // Add the not stripped shader binaries to the database, too. + AddShaderBinaryWithDebugInfo("cube.vert.spirv", "cube.vert.full.spirv"); + AddShaderBinaryWithDebugInfo("cube.frag.spirv", "cube.frag.full.spirv"); +} + +ShaderDatabase::~ShaderDatabase() +{ +} + +bool ShaderDatabase::ReadFile(const char* filename, std::vector& data) +{ + std::ifstream fs(filename, std::ios::in | std::ios::binary); + if (!fs) + { + return false; + } + + fs.seekg(0, std::ios::end); + data.resize(fs.tellg()); + fs.seekg(0, std::ios::beg); + fs.read(reinterpret_cast(data.data()), data.size()); + fs.close(); + + return true; +} + +void ShaderDatabase::AddShaderBinary(const char* shaderFilePath) +{ + // Read the shader binary code from the file + std::vector data; + if (!ReadFile(shaderFilePath, data)) + { + return; + } + + // Create shader hash for the shader + const GFSDK_Aftermath_SpirvCode shader{ data.data(), uint32_t(data.size()) }; + GFSDK_Aftermath_ShaderHash shaderHash; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderHashSpirv( + GFSDK_Aftermath_Version_API, + &shader, + &shaderHash)); + + // Store the data for shader mapping when decoding GPU crash dumps. + // cf. FindShaderBinary() + m_shaderBinaries[shaderHash].swap(data); +} + +void ShaderDatabase::AddShaderBinaryWithDebugInfo(const char* strippedShaderFilePath, const char* shaderFilePath) +{ + // Read the shader debug data from the file + std::vector data; + if (!ReadFile(shaderFilePath, data)) + { + return; + } + std::vector strippedData; + if (!ReadFile(strippedShaderFilePath, strippedData)) + { + return; + } + + // Generate shader debug name. + GFSDK_Aftermath_ShaderDebugName debugName; + const GFSDK_Aftermath_SpirvCode shader{ data.data(), uint32_t(data.size()) }; + const GFSDK_Aftermath_SpirvCode strippedShader{ strippedData.data(), uint32_t(strippedData.size()) }; + AFTERMATH_CHECK_ERROR(GFSDK_Aftermath_GetShaderDebugNameSpirv( + GFSDK_Aftermath_Version_API, + &shader, + &strippedShader, + &debugName)); + + // Store the data for shader instruction address mapping when decoding GPU crash dumps. + // cf. FindShaderBinaryWithDebugData() + m_shaderBinariesWithDebugInfo[debugName].swap(data); +} + +// Find a shader binary by shader hash. +bool ShaderDatabase::FindShaderBinary(const GFSDK_Aftermath_ShaderHash& shaderHash, std::vector& shader) const +{ + // Find shader binary data for the shader hash + auto i_shader = m_shaderBinaries.find(shaderHash); + if (i_shader == m_shaderBinaries.end()) + { + // Nothing found. + return false; + } + + shader = i_shader->second; + return true; +} + +// Find a shader binary with debug information by shader debug name. +bool ShaderDatabase::FindShaderBinaryWithDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& shader) const +{ + // Find shader binary for the shader debug name. + auto i_shader = m_shaderBinariesWithDebugInfo.find(shaderDebugName); + if (i_shader == m_shaderBinariesWithDebugInfo.end()) + { + // Nothing found. + return false; + } + + shader = i_shader->second; + return true; +} diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.h b/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.h new file mode 100644 index 0000000..0402cdb --- /dev/null +++ b/src/Engine/Graphics/Vulkan/NsightAftermathShaderDatabase.h @@ -0,0 +1,64 @@ +//********************************************************* +// +// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +//********************************************************* + +#pragma once + +#include +#include +#include + +#include "NsightAftermathHelpers.h" + +//********************************************************* +// Implements a very simple shader database to help demonstrate +// how to use the Nsight Aftermath GPU crash dump decoder API. +// +// In a real world scenario this would be part of an offline +// analysis tool. This is for demonstration purposes only! +// +class ShaderDatabase +{ +public: + ShaderDatabase(); + ~ShaderDatabase(); + + // Find a shader bytecode binary by shader hash. + bool FindShaderBinary(const GFSDK_Aftermath_ShaderHash& shaderHash, std::vector& shader) const; + + // Find a source shader debug info by shader debug name generated by the DXC compiler. + bool FindShaderBinaryWithDebugData(const GFSDK_Aftermath_ShaderDebugName& shaderDebugName, std::vector& shader) const; + +private: + + void AddShaderBinary(const char* shaderFilePath); + void AddShaderBinaryWithDebugInfo(const char* strippedShaderFilePath, const char* shaderFilePath); + + static bool ReadFile(const char* filename, std::vector& data); + + // List of shader binaries by ShaderHash. + std::map> m_shaderBinaries; + + // List of available shader binaries with source debug information by ShaderDebugName. + std::map> m_shaderBinariesWithDebugInfo; +}; diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index 0ae3b5b..9931d59 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -350,7 +350,7 @@ VkAccessFlags UniformBuffer::getDestAccessMask() } StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData) - : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData.owner) + : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData) , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic) { if (resourceData.resourceData.data != nullptr) @@ -365,6 +365,44 @@ StructuredBuffer::~StructuredBuffer() { } +bool StructuredBuffer::updateContents(const BulkResourceData &resourceData) +{ + Gfx::StructuredBuffer::updateContents(resourceData); + //We always want to update, as the contents could be different on the GPU + void* data = lock(); + std::memcpy(data, resourceData.data, resourceData.size); + unlock(); + return true; +} +void* StructuredBuffer::lock(bool bWriteOnly) +{ + if(dedicatedStagingBuffer != nullptr) + { + return dedicatedStagingBuffer->getMappedPointer(); + } + return ShaderBuffer::lock(bWriteOnly); +} + +void StructuredBuffer::unlock() +{ + if(dedicatedStagingBuffer != nullptr) + { + dedicatedStagingBuffer->flushMappedMemory(); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); + + VkBufferCopy region; + std::memset(®ion, 0, sizeof(VkBufferCopy)); + region.size = ShaderBuffer::size; + vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); + graphics->getQueueCommands(currentOwner)->submitCommands(); + } + else + { + ShaderBuffer::unlock(); + } +} + void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index 68e532d..6794273 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -91,13 +91,12 @@ void CmdBuffer::executeCommands(const Array& commands) for (uint32 i = 0; i < commands.size(); ++i) { auto command = commands[i].cast(); - // Cache array and size to save on pointer access - for(auto boundDescriptor : command->boundDescriptors) - { - boundDescriptor->currentlyBound = this; - } command->end(); executingRenders.add(command); + for(auto descriptor : command->boundDescriptors) + { + boundDescriptors.add(descriptor); + } cmdBuffers[i] = command->getHandle(); } vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); @@ -109,13 +108,12 @@ void CmdBuffer::executeCommands(const Array& commands) for (uint32 i = 0; i < commands.size(); ++i) { auto command = commands[i].cast(); - // Cache array and size to save on pointer access - for(auto boundDescriptor : command->boundDescriptors) - { - boundDescriptor->currentlyBound = this; - } command->end(); executingComputes.add(command); + for(auto descriptor : command->boundDescriptors) + { + boundDescriptors.add(descriptor); + } cmdBuffers[i] = command->getHandle(); } vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data()); @@ -145,6 +143,10 @@ void CmdBuffer::refreshFence() command->reset(); } executingRenders.clear(); + for(auto descriptor : boundDescriptors) + { + descriptor->unbind(); + } state = State::ReadyBegin; } } @@ -196,10 +198,6 @@ void SecondaryCmdBuffer::end() void SecondaryCmdBuffer::reset() { vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); - for(auto boundDescriptor : boundDescriptors) - { - boundDescriptor->currentlyBound = nullptr; - } boundDescriptors.clear(); ready = true; } @@ -251,6 +249,8 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { auto descriptor = descriptorSet.cast(); boundDescriptors.add(descriptor.getHandle()); + descriptor->bind(); + //std::cout << "Binding descriptor " << descriptor->getHandle() << " to cmd " << handle << std::endl; VkDescriptorSet setHandle = descriptor->getHandle(); vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); } @@ -260,6 +260,8 @@ void RenderCommand::bindDescriptor(const Array& descriptorS for(uint32 i = 0; i < descriptorSets.size(); ++i) { auto descriptorSet = descriptorSets[i].cast(); + descriptorSet->bind(); + //std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl; boundDescriptors.add(descriptorSet.getHandle()); sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); } @@ -326,6 +328,8 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) { auto descriptor = descriptorSet.cast(); boundDescriptors.add(descriptor.getHandle()); + descriptor->bind(); + //std::cout << "Binding descriptor " << descriptor->getHandle() << " to cmd " << handle << std::endl; VkDescriptorSet setHandle = descriptor->getHandle(); vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr); } @@ -337,6 +341,8 @@ void ComputeCommand::bindDescriptor(const Array& descriptor { auto descriptorSet = descriptorSets[i].cast(); boundDescriptors.add(descriptorSet.getHandle()); + descriptorSet->bind(); + //std::cout << "Binding descriptor " << descriptorSet->getHandle() << " to cmd " << handle << std::endl; sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle(); } vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr); diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index 4897254..2940d3d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -31,6 +31,7 @@ DEFINE_REF(CmdBufferBase) DECLARE_REF(RenderCommand) DECLARE_REF(ComputeCommand) +DECLARE_REF(DescriptorSet) DECLARE_REF(CommandBufferManager) class CmdBuffer : public CmdBufferBase { @@ -68,6 +69,7 @@ private: Array waitFlags; Array executingRenders; Array executingComputes; + Array boundDescriptors; friend class RenderCommand; friend class CommandBufferManager; friend class Queue; @@ -76,7 +78,6 @@ DEFINE_REF(CmdBuffer) DECLARE_REF(GraphicsPipeline) DECLARE_REF(ComputePipeline) -DECLARE_REF(DescriptorSet) class SecondaryCmdBuffer: public CmdBufferBase { diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index aae194a..bb88fda 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -220,7 +220,7 @@ void DescriptorSet::writeChanges() { if(isCurrentlyBound()) { - currentlyBound->waitForCommand(1000000000u); + std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl; assert(!isCurrentlyBound()); } vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); @@ -289,7 +289,6 @@ void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorS { //If it hasnt been initialized, allocate it VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle)); - } cachedHandles[setIndex]->currentlyInUse = true; descriptorSet = cachedHandles[setIndex]; diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 1cc5407..b88ab1d 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -64,7 +64,7 @@ public: , graphics(graphics) , owner(owner) , currentlyInUse(false) - , currentlyBound(nullptr) + , currentlyBound(false) { } virtual ~DescriptorSet(); @@ -77,12 +77,20 @@ public: inline bool isCurrentlyBound() const { - return currentlyBound != nullptr; + return currentlyBound; } inline bool isCurrentlyInUse() const { return currentlyInUse; } + void bind() + { + currentlyBound = true; + } + void unbind() + { + currentlyBound = false; + } void free() { currentlyInUse = false; @@ -104,7 +112,8 @@ private: VkDescriptorSet setHandle; PGraphics graphics; PDescriptorAllocator owner; - PCmdBuffer currentlyBound; + //PCmdBuffer currentlyBound; + bool currentlyBound; bool currentlyInUse; friend class DescriptorAllocator; friend class CmdBuffer; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index 184010d..41ceb60 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -412,6 +412,8 @@ void Graphics::setupDebugCallback() VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT); VK_CHECK(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback)); + + crashTracker.Initialize(); } void Graphics::pickPhysicalDevice() @@ -537,6 +539,16 @@ void Graphics::createDevice(GraphicsInitializer initializer) queueInfos.data(), (uint32)queueInfos.size(), &features); +#if ENABLE_VALIDATION + VkDeviceDiagnosticsConfigCreateInfoNV crashDiagInfo; + crashDiagInfo.sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV; + crashDiagInfo.pNext = nullptr; + crashDiagInfo.flags = + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_RESOURCE_TRACKING_BIT_NV | + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_AUTOMATIC_CHECKPOINTS_BIT_NV | + VK_DEVICE_DIAGNOSTICS_CONFIG_ENABLE_SHADER_DEBUG_INFO_BIT_NV; + deviceInfo.pNext = &crashDiagInfo; +#endif deviceInfo.enabledExtensionCount = (uint32)initializer.deviceExtensions.size(); deviceInfo.ppEnabledExtensionNames = initializer.deviceExtensions.data(); deviceInfo.enabledLayerCount = (uint32_t)initializer.layers.size(); diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.h b/src/Engine/Graphics/Vulkan/VulkanGraphics.h index 09d1507..ed9befe 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.h @@ -1,6 +1,7 @@ #pragma once #include "VulkanGraphicsResources.h" #include "Graphics/Graphics.h" +#include "NsightAftermathGpuCrashTracker.h" namespace Seele { @@ -98,6 +99,7 @@ protected: Map allocatedFramebuffers; PAllocator allocator; PStagingManager stagingManager; + GpuCrashTracker crashTracker; friend class Window; }; diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h index e69297a..03aa288 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsEnums.h @@ -8,6 +8,10 @@ VkResult res = (f); \ if (res != VK_SUCCESS) \ { \ + if(res == VK_ERROR_DEVICE_LOST) \ + { \ + std::this_thread::sleep_for(std::chrono::seconds(3)); \ + } \ std::cout << "Fatal : VkResult is \"" << res << "\" in " << __FILE__ << " at line " << __LINE__ << std::endl; \ assert(res == VK_SUCCESS); \ } \ diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h index 0a9ebfa..02d4148 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h @@ -160,7 +160,10 @@ class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer public: StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData); virtual ~StructuredBuffer(); + virtual bool updateContents(const BulkResourceData &resourceData); + virtual void* lock(bool bWriteOnly = true) override; + virtual void unlock() override; protected: // Inherited via Vulkan::Buffer virtual VkAccessFlags getSourceAccessMask(); diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp index 9ecb70c..2d591f6 100644 --- a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp @@ -370,7 +370,11 @@ PComputePipeline PipelineCache::createPipeline(const ComputePipelineCreateInfo& computeStage->getModuleHandle(), computeStage->getEntryPointName()); VkPipeline pipelineHandle; + auto beginTime = std::chrono::high_resolution_clock::now(); VK_CHECK(vkCreateComputePipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle)); + auto endTime = std::chrono::high_resolution_clock::now(); + int64 delta = std::chrono::duration_cast(endTime - beginTime).count(); + std::cout << "Compute creation time: " << delta << std::endl; PComputePipeline result = new ComputePipeline(graphics, pipelineHandle, layout, computeInfo); return result; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp index 3080b80..fe820cd 100644 --- a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp @@ -22,44 +22,44 @@ Queue::~Queue() void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores) { + + std::scoped_lock lck(queueLock); + assert(cmdBuffer->state == CmdBuffer::State::Ended); + + PFence fence = cmdBuffer->fence; + assert(!fence->isSignaled()); + + const VkCommandBuffer cmdBuffers[] = {cmdBuffer->handle}; + + VkSubmitInfo submitInfo = + init::SubmitInfo(); + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = cmdBuffers; + submitInfo.signalSemaphoreCount = static_cast(numSignalSemaphores); + submitInfo.pSignalSemaphores = signalSemaphores; + + Array waitSemaphores; + if (cmdBuffer->waitSemaphores.size() > 0) { - std::scoped_lock lck(queueLock); - assert(cmdBuffer->state == CmdBuffer::State::Ended); - - PFence fence = cmdBuffer->fence; - assert(!fence->isSignaled()); - - const VkCommandBuffer cmdBuffers[] = {cmdBuffer->handle}; - - VkSubmitInfo submitInfo = - init::SubmitInfo(); - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = cmdBuffers; - submitInfo.signalSemaphoreCount = static_cast(numSignalSemaphores); - submitInfo.pSignalSemaphores = signalSemaphores; - - Array waitSemaphores; - if (cmdBuffer->waitSemaphores.size() > 0) + for (PSemaphore semaphore : cmdBuffer->waitSemaphores) { - for (PSemaphore semaphore : cmdBuffer->waitSemaphores) - { - waitSemaphores.add(semaphore->getHandle()); - } - submitInfo.waitSemaphoreCount = static_cast(cmdBuffer->waitSemaphores.size()); - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.pWaitDstStageMask = cmdBuffer->waitFlags.data(); + waitSemaphores.add(semaphore->getHandle()); } - VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle())); - cmdBuffer->state = CmdBuffer::State::Submitted; - cmdBuffer->waitFlags.clear(); - cmdBuffer->waitSemaphores.clear(); - - if (Gfx::waitIdleOnSubmit) - { - fence->wait(200 * 1000ull); - } - - cmdBuffer->refreshFence(); - graphics->getStagingManager()->clearPending(); + submitInfo.waitSemaphoreCount = static_cast(cmdBuffer->waitSemaphores.size()); + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.pWaitDstStageMask = cmdBuffer->waitFlags.data(); } + VK_CHECK(vkQueueSubmit(queue, 1, &submitInfo, fence->getHandle())); + cmdBuffer->state = CmdBuffer::State::Submitted; + cmdBuffer->waitFlags.clear(); + cmdBuffer->waitSemaphores.clear(); + + if (Gfx::waitIdleOnSubmit) + { + fence->wait(200 * 1000ull); + } + + cmdBuffer->refreshFence(); + graphics->getStagingManager()->clearPending(); + } \ No newline at end of file diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 581004c..1be78d6 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -137,11 +137,11 @@ void Material::compile() uniformInitializer.resourceData.size = uniformDataSize; uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer); } - layout->create(); BRDF* brdf = BRDF::getBRDFByName(profile); brdf->generateMaterialCode(codeStream, j["code"]); codeStream << "};"; codeStream.close(); + layout->create(); setStatus(Status::Ready); } diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index d06ba7d..904889f 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -17,24 +17,25 @@ Scene::Scene(Gfx::PGraphics graphics) , updater(new SceneUpdater()) { lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1); - lightEnv.directionalLights[0].direction = Vector4(1, 0, 0, 1); + lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1); lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1); - lightEnv.numDirectionalLights = 1; + lightEnv.numDirectionalLights = 0; srand((unsigned int)time(NULL)); - for(uint32 i = 0; i < MAX_POINT_LIGHTS; ++i) + for(uint32 i = 0; i < MAX_POINT_LIGHTS/2; ++i) { lightEnv.pointLights[i].colorRange = Vector4(frand(), frand(), frand(), frand() * 30); - lightEnv.pointLights[i].positionWS = Vector4(frand() * 200-100, frand(), frand() * 200-100, 1); + lightEnv.pointLights[i].positionWS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1); + lightEnv.pointLights[i].positionVS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1); } - lightEnv.numPointLights = MAX_POINT_LIGHTS; + lightEnv.numPointLights = MAX_POINT_LIGHTS/2; BulkResourceData lightInit; - StructuredBufferCreateInfo structuredInfo; + UniformBufferCreateInfo structuredInfo; lightInit.size = sizeof(LightEnv); lightInit.data = (uint8*)&lightEnv; structuredInfo.resourceData = lightInit; structuredInfo.bDynamic = false; - lightBuffer = graphics->createStructuredBuffer(structuredInfo); + lightBuffer = graphics->createUniformBuffer(structuredInfo); } Scene::~Scene() diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 238eeef..81d0db8 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -46,14 +46,14 @@ public: const Array& getPrimitives() const { return primitives; } const Array& getStaticMeshes() const { return staticMeshes; } - const Gfx::PStructuredBuffer& getLightBuffer() const { return lightBuffer; } + const Gfx::PUniformBuffer& getLightBuffer() const { return lightBuffer; } UPSceneUpdater& getSceneUpdater() { return updater; } private: Array staticMeshes; Array rootActors; Array primitives; LightEnv lightEnv; - Gfx::PStructuredBuffer lightBuffer; + Gfx::PUniformBuffer lightBuffer; Gfx::PGraphics graphics; UPSceneUpdater updater; };