summaryrefslogtreecommitdiff
path: root/src/video_core/vulkan_common
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-12-26 01:26:52 -0300
committerGravatar ReinUsesLisp2021-01-04 02:22:22 -0300
commitd235cf393399c386a59b5e39d39bc9efb161aea0 (patch)
tree4b8a3420a94b972dfc0781ed1ba8b197b8b02c95 /src/video_core/vulkan_common
parentrenderer_vulkan: Move device abstraction to vulkan_common (diff)
downloadyuzu-d235cf393399c386a59b5e39d39bc9efb161aea0.tar.gz
yuzu-d235cf393399c386a59b5e39d39bc9efb161aea0.tar.xz
yuzu-d235cf393399c386a59b5e39d39bc9efb161aea0.zip
renderer_vulkan/nsight_aftermath_tracker: Move to vulkan_common
Diffstat (limited to 'src/video_core/vulkan_common')
-rw-r--r--src/video_core/vulkan_common/nsight_aftermath_tracker.cpp212
-rw-r--r--src/video_core/vulkan_common/nsight_aftermath_tracker.h82
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp7
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h5
4 files changed, 302 insertions, 4 deletions
diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp
new file mode 100644
index 000000000..8d10ac29e
--- /dev/null
+++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.cpp
@@ -0,0 +1,212 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#ifdef HAS_NSIGHT_AFTERMATH
6
7#include <mutex>
8#include <string>
9#include <string_view>
10#include <utility>
11#include <vector>
12
13#include <fmt/format.h>
14
15#define VK_NO_PROTOTYPES
16#include <vulkan/vulkan.h>
17
18#include <GFSDK_Aftermath.h>
19#include <GFSDK_Aftermath_Defines.h>
20#include <GFSDK_Aftermath_GpuCrashDump.h>
21#include <GFSDK_Aftermath_GpuCrashDumpDecoding.h>
22
23#include "common/common_paths.h"
24#include "common/common_types.h"
25#include "common/file_util.h"
26#include "common/logging/log.h"
27#include "common/scope_exit.h"
28
29#include "video_core/renderer_vulkan/nsight_aftermath_tracker.h"
30
31namespace Vulkan {
32
33static constexpr char AFTERMATH_LIB_NAME[] = "GFSDK_Aftermath_Lib.x64.dll";
34
35NsightAftermathTracker::NsightAftermathTracker() {
36 if (!dl.Open(AFTERMATH_LIB_NAME)) {
37 LOG_ERROR(Render_Vulkan, "Failed to load Nsight Aftermath DLL");
38 return;
39 }
40 if (!dl.GetSymbol("GFSDK_Aftermath_DisableGpuCrashDumps",
41 &GFSDK_Aftermath_DisableGpuCrashDumps) ||
42 !dl.GetSymbol("GFSDK_Aftermath_EnableGpuCrashDumps",
43 &GFSDK_Aftermath_EnableGpuCrashDumps) ||
44 !dl.GetSymbol("GFSDK_Aftermath_GetShaderDebugInfoIdentifier",
45 &GFSDK_Aftermath_GetShaderDebugInfoIdentifier) ||
46 !dl.GetSymbol("GFSDK_Aftermath_GetShaderHashSpirv", &GFSDK_Aftermath_GetShaderHashSpirv) ||
47 !dl.GetSymbol("GFSDK_Aftermath_GpuCrashDump_CreateDecoder",
48 &GFSDK_Aftermath_GpuCrashDump_CreateDecoder) ||
49 !dl.GetSymbol("GFSDK_Aftermath_GpuCrashDump_DestroyDecoder",
50 &GFSDK_Aftermath_GpuCrashDump_DestroyDecoder) ||
51 !dl.GetSymbol("GFSDK_Aftermath_GpuCrashDump_GenerateJSON",
52 &GFSDK_Aftermath_GpuCrashDump_GenerateJSON) ||
53 !dl.GetSymbol("GFSDK_Aftermath_GpuCrashDump_GetJSON",
54 &GFSDK_Aftermath_GpuCrashDump_GetJSON)) {
55 LOG_ERROR(Render_Vulkan, "Failed to load Nsight Aftermath function pointers");
56 return false;
57 }
58 dump_dir = Common::FS::GetUserPath(Common::FS::UserPath::LogDir) + "gpucrash";
59
60 void(Common::FS::DeleteDirRecursively(dump_dir));
61 if (!Common::FS::CreateDir(dump_dir)) {
62 LOG_ERROR(Render_Vulkan, "Failed to create Nsight Aftermath dump directory");
63 return;
64 }
65 if (!GFSDK_Aftermath_SUCCEED(GFSDK_Aftermath_EnableGpuCrashDumps(
66 GFSDK_Aftermath_Version_API, GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan,
67 GFSDK_Aftermath_GpuCrashDumpFeatureFlags_Default, GpuCrashDumpCallback,
68 ShaderDebugInfoCallback, CrashDumpDescriptionCallback, this))) {
69 LOG_ERROR(Render_Vulkan, "GFSDK_Aftermath_EnableGpuCrashDumps failed");
70 return;
71 }
72 LOG_INFO(Render_Vulkan, "Nsight Aftermath dump directory is \"{}\"", dump_dir);
73 initialized = true;
74}
75
76NsightAftermathTracker::~NsightAftermathTracker() {
77 if (initialized) {
78 (void)GFSDK_Aftermath_DisableGpuCrashDumps();
79 }
80}
81
82void NsightAftermathTracker::SaveShader(const std::vector<u32>& spirv) const {
83 if (!initialized) {
84 return;
85 }
86
87 std::vector<u32> spirv_copy = spirv;
88 GFSDK_Aftermath_SpirvCode shader;
89 shader.pData = spirv_copy.data();
90 shader.size = static_cast<u32>(spirv_copy.size() * 4);
91
92 std::scoped_lock lock{mutex};
93
94 GFSDK_Aftermath_ShaderHash hash;
95 if (!GFSDK_Aftermath_SUCCEED(
96 GFSDK_Aftermath_GetShaderHashSpirv(GFSDK_Aftermath_Version_API, &shader, &hash))) {
97 LOG_ERROR(Render_Vulkan, "Failed to hash SPIR-V module");
98 return;
99 }
100
101 Common::FS::IOFile file(fmt::format("{}/source_{:016x}.spv", dump_dir, hash.hash), "wb");
102 if (!file.IsOpen()) {
103 LOG_ERROR(Render_Vulkan, "Failed to dump SPIR-V module with hash={:016x}", hash.hash);
104 return;
105 }
106 if (file.WriteArray(spirv.data(), spirv.size()) != spirv.size()) {
107 LOG_ERROR(Render_Vulkan, "Failed to write SPIR-V module with hash={:016x}", hash.hash);
108 return;
109 }
110}
111
112void NsightAftermathTracker::OnGpuCrashDumpCallback(const void* gpu_crash_dump,
113 u32 gpu_crash_dump_size) {
114 std::scoped_lock lock{mutex};
115
116 LOG_CRITICAL(Render_Vulkan, "called");
117
118 GFSDK_Aftermath_GpuCrashDump_Decoder decoder;
119 if (!GFSDK_Aftermath_SUCCEED(GFSDK_Aftermath_GpuCrashDump_CreateDecoder(
120 GFSDK_Aftermath_Version_API, gpu_crash_dump, gpu_crash_dump_size, &decoder))) {
121 LOG_ERROR(Render_Vulkan, "Failed to create decoder");
122 return;
123 }
124 SCOPE_EXIT({ GFSDK_Aftermath_GpuCrashDump_DestroyDecoder(decoder); });
125
126 u32 json_size = 0;
127 if (!GFSDK_Aftermath_SUCCEED(GFSDK_Aftermath_GpuCrashDump_GenerateJSON(
128 decoder, GFSDK_Aftermath_GpuCrashDumpDecoderFlags_ALL_INFO,
129 GFSDK_Aftermath_GpuCrashDumpFormatterFlags_NONE, nullptr, nullptr, nullptr, nullptr,
130 this, &json_size))) {
131 LOG_ERROR(Render_Vulkan, "Failed to generate JSON");
132 return;
133 }
134 std::vector<char> json(json_size);
135 if (!GFSDK_Aftermath_SUCCEED(
136 GFSDK_Aftermath_GpuCrashDump_GetJSON(decoder, json_size, json.data()))) {
137 LOG_ERROR(Render_Vulkan, "Failed to query JSON");
138 return;
139 }
140
141 const std::string base_name = [this] {
142 const int id = dump_id++;
143 if (id == 0) {
144 return fmt::format("{}/crash.nv-gpudmp", dump_dir);
145 } else {
146 return fmt::format("{}/crash_{}.nv-gpudmp", dump_dir, id);
147 }
148 }();
149
150 std::string_view dump_view(static_cast<const char*>(gpu_crash_dump), gpu_crash_dump_size);
151 if (Common::FS::WriteStringToFile(false, base_name, dump_view) != gpu_crash_dump_size) {
152 LOG_ERROR(Render_Vulkan, "Failed to write dump file");
153 return;
154 }
155 const std::string_view json_view(json.data(), json.size());
156 if (Common::FS::WriteStringToFile(true, base_name + ".json", json_view) != json.size()) {
157 LOG_ERROR(Render_Vulkan, "Failed to write JSON");
158 return;
159 }
160}
161
162void NsightAftermathTracker::OnShaderDebugInfoCallback(const void* shader_debug_info,
163 u32 shader_debug_info_size) {
164 std::scoped_lock lock{mutex};
165
166 GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier;
167 if (!GFSDK_Aftermath_SUCCEED(GFSDK_Aftermath_GetShaderDebugInfoIdentifier(
168 GFSDK_Aftermath_Version_API, shader_debug_info, shader_debug_info_size, &identifier))) {
169 LOG_ERROR(Render_Vulkan, "GFSDK_Aftermath_GetShaderDebugInfoIdentifier failed");
170 return;
171 }
172
173 const std::string path =
174 fmt::format("{}/shader_{:016x}{:016x}.nvdbg", dump_dir, identifier.id[0], identifier.id[1]);
175 Common::FS::IOFile file(path, "wb");
176 if (!file.IsOpen()) {
177 LOG_ERROR(Render_Vulkan, "Failed to create file {}", path);
178 return;
179 }
180 if (file.WriteBytes(static_cast<const u8*>(shader_debug_info), shader_debug_info_size) !=
181 shader_debug_info_size) {
182 LOG_ERROR(Render_Vulkan, "Failed to write file {}", path);
183 return;
184 }
185}
186
187void NsightAftermathTracker::OnCrashDumpDescriptionCallback(
188 PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription add_description) {
189 add_description(GFSDK_Aftermath_GpuCrashDumpDescriptionKey_ApplicationName, "yuzu");
190}
191
192void NsightAftermathTracker::GpuCrashDumpCallback(const void* gpu_crash_dump,
193 u32 gpu_crash_dump_size, void* user_data) {
194 static_cast<NsightAftermathTracker*>(user_data)->OnGpuCrashDumpCallback(gpu_crash_dump,
195 gpu_crash_dump_size);
196}
197
198void NsightAftermathTracker::ShaderDebugInfoCallback(const void* shader_debug_info,
199 u32 shader_debug_info_size, void* user_data) {
200 static_cast<NsightAftermathTracker*>(user_data)->OnShaderDebugInfoCallback(
201 shader_debug_info, shader_debug_info_size);
202}
203
204void NsightAftermathTracker::CrashDumpDescriptionCallback(
205 PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription add_description, void* user_data) {
206 static_cast<NsightAftermathTracker*>(user_data)->OnCrashDumpDescriptionCallback(
207 add_description);
208}
209
210} // namespace Vulkan
211
212#endif // HAS_NSIGHT_AFTERMATH
diff --git a/src/video_core/vulkan_common/nsight_aftermath_tracker.h b/src/video_core/vulkan_common/nsight_aftermath_tracker.h
new file mode 100644
index 000000000..cee3847fb
--- /dev/null
+++ b/src/video_core/vulkan_common/nsight_aftermath_tracker.h
@@ -0,0 +1,82 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <mutex>
8#include <string>
9#include <vector>
10
11#define VK_NO_PROTOTYPES
12#include <vulkan/vulkan.h>
13
14#ifdef HAS_NSIGHT_AFTERMATH
15#include <GFSDK_Aftermath_Defines.h>
16#include <GFSDK_Aftermath_GpuCrashDump.h>
17#include <GFSDK_Aftermath_GpuCrashDumpDecoding.h>
18#endif
19
20#include "common/common_types.h"
21#include "common/dynamic_library.h"
22
23namespace Vulkan {
24
25class NsightAftermathTracker {
26public:
27 NsightAftermathTracker();
28 ~NsightAftermathTracker();
29
30 NsightAftermathTracker(const NsightAftermathTracker&) = delete;
31 NsightAftermathTracker& operator=(const NsightAftermathTracker&) = delete;
32
33 // Delete move semantics because Aftermath initialization uses a pointer to this.
34 NsightAftermathTracker(NsightAftermathTracker&&) = delete;
35 NsightAftermathTracker& operator=(NsightAftermathTracker&&) = delete;
36
37 void SaveShader(const std::vector<u32>& spirv) const;
38
39private:
40#ifdef HAS_NSIGHT_AFTERMATH
41 static void GpuCrashDumpCallback(const void* gpu_crash_dump, u32 gpu_crash_dump_size,
42 void* user_data);
43
44 static void ShaderDebugInfoCallback(const void* shader_debug_info, u32 shader_debug_info_size,
45 void* user_data);
46
47 static void CrashDumpDescriptionCallback(
48 PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription add_description, void* user_data);
49
50 void OnGpuCrashDumpCallback(const void* gpu_crash_dump, u32 gpu_crash_dump_size);
51
52 void OnShaderDebugInfoCallback(const void* shader_debug_info, u32 shader_debug_info_size);
53
54 void OnCrashDumpDescriptionCallback(
55 PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription add_description);
56
57 mutable std::mutex mutex;
58
59 std::string dump_dir;
60 int dump_id = 0;
61
62 bool initialized = false;
63
64 Common::DynamicLibrary dl;
65 PFN_GFSDK_Aftermath_DisableGpuCrashDumps GFSDK_Aftermath_DisableGpuCrashDumps;
66 PFN_GFSDK_Aftermath_EnableGpuCrashDumps GFSDK_Aftermath_EnableGpuCrashDumps;
67 PFN_GFSDK_Aftermath_GetShaderDebugInfoIdentifier GFSDK_Aftermath_GetShaderDebugInfoIdentifier;
68 PFN_GFSDK_Aftermath_GetShaderHashSpirv GFSDK_Aftermath_GetShaderHashSpirv;
69 PFN_GFSDK_Aftermath_GpuCrashDump_CreateDecoder GFSDK_Aftermath_GpuCrashDump_CreateDecoder;
70 PFN_GFSDK_Aftermath_GpuCrashDump_DestroyDecoder GFSDK_Aftermath_GpuCrashDump_DestroyDecoder;
71 PFN_GFSDK_Aftermath_GpuCrashDump_GenerateJSON GFSDK_Aftermath_GpuCrashDump_GenerateJSON;
72 PFN_GFSDK_Aftermath_GpuCrashDump_GetJSON GFSDK_Aftermath_GpuCrashDump_GetJSON;
73#endif
74};
75
76#ifndef HAS_NSIGHT_AFTERMATH
77inline NsightAftermathTracker::NsightAftermathTracker() = default;
78inline NsightAftermathTracker::~NsightAftermathTracker() = default;
79inline void NsightAftermathTracker::SaveShader(const std::vector<u32>&) const {}
80#endif
81
82} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 67183eed8..f300f22c9 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -13,6 +13,7 @@
13 13
14#include "common/assert.h" 14#include "common/assert.h"
15#include "core/settings.h" 15#include "core/settings.h"
16#include "video_core/vulkan_common/nsight_aftermath_tracker.h"
16#include "video_core/vulkan_common/vulkan_device.h" 17#include "video_core/vulkan_common/vulkan_device.h"
17#include "video_core/vulkan_common/vulkan_wrapper.h" 18#include "video_core/vulkan_common/vulkan_wrapper.h"
18 19
@@ -412,7 +413,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
412 413
413 VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv; 414 VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv;
414 if (nv_device_diagnostics_config) { 415 if (nv_device_diagnostics_config) {
415 nsight_aftermath_tracker.Initialize(); 416 nsight_aftermath_tracker = std::make_unique<NsightAftermathTracker>();
416 417
417 diagnostics_nv = { 418 diagnostics_nv = {
418 .sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV, 419 .sType = VK_STRUCTURE_TYPE_DEVICE_DIAGNOSTICS_CONFIG_CREATE_INFO_NV,
@@ -491,7 +492,9 @@ void Device::ReportLoss() const {
491} 492}
492 493
493void Device::SaveShader(const std::vector<u32>& spirv) const { 494void Device::SaveShader(const std::vector<u32>& spirv) const {
494 nsight_aftermath_tracker.SaveShader(spirv); 495 if (nsight_aftermath_tracker) {
496 nsight_aftermath_tracker->SaveShader(spirv);
497 }
495} 498}
496 499
497bool Device::IsOptimalAstcSupported(const VkPhysicalDeviceFeatures& features) const { 500bool Device::IsOptimalAstcSupported(const VkPhysicalDeviceFeatures& features) const {
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index b2651e049..a973c3ce4 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -10,11 +10,12 @@
10#include <vector> 10#include <vector>
11 11
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "video_core/renderer_vulkan/nsight_aftermath_tracker.h"
14#include "video_core/vulkan_common/vulkan_wrapper.h" 13#include "video_core/vulkan_common/vulkan_wrapper.h"
15 14
16namespace Vulkan { 15namespace Vulkan {
17 16
17class NsightAftermathTracker;
18
18/// Format usage descriptor. 19/// Format usage descriptor.
19enum class FormatType { Linear, Optimal, Buffer }; 20enum class FormatType { Linear, Optimal, Buffer };
20 21
@@ -300,7 +301,7 @@ private:
300 std::unordered_map<VkFormat, VkFormatProperties> format_properties; 301 std::unordered_map<VkFormat, VkFormatProperties> format_properties;
301 302
302 /// Nsight Aftermath GPU crash tracker 303 /// Nsight Aftermath GPU crash tracker
303 NsightAftermathTracker nsight_aftermath_tracker; 304 std::unique_ptr<NsightAftermathTracker> nsight_aftermath_tracker;
304}; 305};
305 306
306} // namespace Vulkan 307} // namespace Vulkan