adding aftermath debugging and fixing forward plus

This commit is contained in:
Dynamitos
2021-06-04 18:27:49 +02:00
parent e00b382d4a
commit 22adb08bfc
40 changed files with 4669 additions and 112 deletions
+6 -1
View File
@@ -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 $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_BINARIES} $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_GLSLANG} $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GLFW_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ASSIMP_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${NSAM_BINARIES} $<TARGET_FILE_DIR:SeeleEngine>
DEPENDS SeeleEngine)
+114
View File
@@ -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)
+601
View File
@@ -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 dont have the required age or authority to accept this Agreement, or if you dont
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 NVIDIAs 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 didnt 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 attorneys 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 NVIDIAs 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 dont 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 NVIDIAS 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 NVIDIAs 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 NVIDIAs 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 Treasurys 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
+889
View File
@@ -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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<char const*> 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<std::mutex> 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<std::mutex> 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<GFSDK_Aftermath_GpuCrashDump_ShaderInfo> 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<char> 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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<uint8_t> 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<uint8_t> 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<uint8_t> 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.
+483
View File
@@ -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
+236
View File
@@ -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 <cstdint>
#else
#include <stdint.h>
#include <stdbool.h>
#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
@@ -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
@@ -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
@@ -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
+9 -10
View File
@@ -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);
}
+6 -15
View File
@@ -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 )
{
+1 -1
View File
@@ -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<ViewParameter> gViewParams;
+1 -1
View File
@@ -69,4 +69,4 @@ struct Lights
};
layout(set = INDEX_LIGHT_ENV, binding = 0, std430)
StructuredBuffer<Lights> gLightEnv;
ConstantBuffer<Lights> gLightEnv;
+1 -1
View File
@@ -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;
+14 -2
View File
@@ -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)
+19 -1
View File
@@ -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<uint8> contents;
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage,
+7 -2
View File
@@ -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();
@@ -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())
@@ -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<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
viewParams.screenDimensions = Vector2(static_cast<float>(viewportWidth), static_cast<float>(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<Gfx::PComputeCommand> 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);
}
+2 -2
View File
@@ -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;
@@ -1,5 +1,10 @@
target_sources(SeeleEngine
PRIVATE
NsightAftermathGpuCrashTracker.h
NsightAftermathGpuCrashTracker.cpp
NsightAftermathHelpers.h
NsightAftermathShaderDatabase.h
NsightAftermathShaderDatabase.cpp
VulkanAllocator.h
VulkanAllocator.cpp
VulkanBuffer.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 <fstream>
#include <iomanip>
#include <string>
#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<std::mutex> 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<std::mutex> 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<uint8_t> 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<char> 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<char> 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<uint8_t> 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<uint8_t> 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<GpuCrashTracker*>(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<GpuCrashTracker*>(pUserData);
pGpuCrashTracker->OnShaderDebugInfo(pShaderDebugInfo, shaderDebugInfoSize);
}
// Static callback wrapper for OnDescription
void GpuCrashTracker::CrashDumpDescriptionCallback(
PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription,
void* pUserData)
{
GpuCrashTracker* pGpuCrashTracker = reinterpret_cast<GpuCrashTracker*>(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<GpuCrashTracker*>(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<GpuCrashTracker*>(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<GpuCrashTracker*>(pUserData);
pGpuCrashTracker->OnShaderSourceDebugInfoLookup(*pShaderDebugName, setShaderBinary);
}
@@ -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 <map>
#include <mutex>
#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<GFSDK_Aftermath_ShaderDebugInfoIdentifier, std::vector<uint8_t>> m_shaderDebugInfo;
// The mock shader database.
ShaderDatabase m_shaderDatabase;
};
@@ -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 <iomanip>
#include <string>
#include <sstream>
#include <vulkan/vulkan.hpp>
#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<typename T>
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<uint32_t>(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
@@ -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 <fstream>
#include <iomanip>
#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<uint8_t>& 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<char*>(data.data()), data.size());
fs.close();
return true;
}
void ShaderDatabase::AddShaderBinary(const char* shaderFilePath)
{
// Read the shader binary code from the file
std::vector<uint8_t> 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<uint8_t> data;
if (!ReadFile(shaderFilePath, data))
{
return;
}
std::vector<uint8_t> 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<uint8_t>& 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<uint8_t>& 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;
}
@@ -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 <vector>
#include <map>
#include <mutex>
#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<uint8_t>& 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<uint8_t>& shader) const;
private:
void AddShaderBinary(const char* shaderFilePath);
void AddShaderBinaryWithDebugInfo(const char* strippedShaderFilePath, const char* shaderFilePath);
static bool ReadFile(const char* filename, std::vector<uint8_t>& data);
// List of shader binaries by ShaderHash.
std::map<GFSDK_Aftermath_ShaderHash, std::vector<uint8_t>> m_shaderBinaries;
// List of available shader binaries with source debug information by ShaderDebugName.
std::map<GFSDK_Aftermath_ShaderDebugName, std::vector<uint8_t>> m_shaderBinariesWithDebugInfo;
};
+39 -1
View File
@@ -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(&region, 0, sizeof(VkBufferCopy));
region.size = ShaderBuffer::size;
vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(currentOwner)->submitCommands();
}
else
{
ShaderBuffer::unlock();
}
}
void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
@@ -91,13 +91,12 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
for (uint32 i = 0; i < commands.size(); ++i)
{
auto command = commands[i].cast<RenderCommand>();
// 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<Gfx::PComputeCommand>& commands)
for (uint32 i = 0; i < commands.size(); ++i)
{
auto command = commands[i].cast<ComputeCommand>();
// 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<DescriptorSet>();
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<Gfx::PDescriptorSet>& descriptorS
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
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<DescriptorSet>();
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<Gfx::PDescriptorSet>& descriptor
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
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);
@@ -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<VkPipelineStageFlags> waitFlags;
Array<PRenderCommand> executingRenders;
Array<PComputeCommand> executingComputes;
Array<DescriptorSet*> 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
{
@@ -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];
@@ -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;
@@ -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();
@@ -1,6 +1,7 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Graphics/Graphics.h"
#include "NsightAftermathGpuCrashTracker.h"
namespace Seele
{
@@ -98,6 +99,7 @@ protected:
Map<uint32, PFramebuffer> allocatedFramebuffers;
PAllocator allocator;
PStagingManager stagingManager;
GpuCrashTracker crashTracker;
friend class Window;
};
@@ -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); \
} \
@@ -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();
@@ -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<std::chrono::microseconds>(endTime - beginTime).count();
std::cout << "Compute creation time: " << delta << std::endl;
PComputePipeline result = new ComputePipeline(graphics, pipelineHandle, layout, computeInfo);
return result;
}
+36 -36
View File
@@ -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<uint32>(numSignalSemaphores);
submitInfo.pSignalSemaphores = signalSemaphores;
Array<VkSemaphore> 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<uint32>(numSignalSemaphores);
submitInfo.pSignalSemaphores = signalSemaphores;
Array<VkSemaphore> waitSemaphores;
if (cmdBuffer->waitSemaphores.size() > 0)
for (PSemaphore semaphore : cmdBuffer->waitSemaphores)
{
for (PSemaphore semaphore : cmdBuffer->waitSemaphores)
{
waitSemaphores.add(semaphore->getHandle());
}
submitInfo.waitSemaphoreCount = static_cast<uint32>(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<uint32>(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();
}
+1 -1
View File
@@ -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);
}
+8 -7
View File
@@ -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()
+2 -2
View File
@@ -46,14 +46,14 @@ public:
const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const Array<MeshBatch>& getStaticMeshes() const { return staticMeshes; }
const Gfx::PStructuredBuffer& getLightBuffer() const { return lightBuffer; }
const Gfx::PUniformBuffer& getLightBuffer() const { return lightBuffer; }
UPSceneUpdater& getSceneUpdater() { return updater; }
private:
Array<MeshBatch> staticMeshes;
Array<PActor> rootActors;
Array<PPrimitiveComponent> primitives;
LightEnv lightEnv;
Gfx::PStructuredBuffer lightBuffer;
Gfx::PUniformBuffer lightBuffer;
Gfx::PGraphics graphics;
UPSceneUpdater updater;
};