video_core: added VK_LAYER_LUNARG_crash_diagnostic (#751)

This commit is contained in:
psucien 2024-09-03 21:56:23 +02:00 committed by GitHub
parent e9ef726185
commit 34ffd95306
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 76 additions and 70 deletions

View file

@ -30,7 +30,9 @@ static bool vkValidation = false;
static bool vkValidationSync = false;
static bool vkValidationGpu = false;
static bool rdocEnable = false;
static bool rdocMarkersEnable = false;
static bool vkMarkers = false;
static bool vkCrashDiagnostic = false;
// Gui
std::string settings_install_dir = "";
u32 main_window_geometry_x = 400;
@ -121,7 +123,7 @@ bool isRdocEnabled() {
}
bool isMarkersEnabled() {
return rdocMarkersEnable;
return vkMarkers;
}
u32 vblankDiv() {
@ -140,6 +142,14 @@ bool vkValidationGpuEnabled() {
return vkValidationGpu;
}
bool vkMarkersEnabled() {
return vkMarkers || vkCrashDiagnostic; // Crash diagnostic forces markers on
}
bool vkCrashDiagnosticEnabled() {
return vkCrashDiagnostic;
}
void setGpuId(s32 selectedGpuId) {
gpuId = selectedGpuId;
}
@ -384,7 +394,8 @@ void load(const std::filesystem::path& path) {
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true);
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
rdocMarkersEnable = toml::find_or<bool>(vk, "rdocMarkersEnable", false);
vkMarkers = toml::find_or<bool>(vk, "rdocMarkersEnable", false);
vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", false);
}
if (data.contains("Debug")) {
@ -460,7 +471,8 @@ void save(const std::filesystem::path& path) {
data["Vulkan"]["validation_sync"] = vkValidationSync;
data["Vulkan"]["validation_gpu"] = vkValidationGpu;
data["Vulkan"]["rdocEnable"] = rdocEnable;
data["Vulkan"]["rdocMarkersEnable"] = rdocMarkersEnable;
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
data["Debug"]["DebugDump"] = isDebugDump;
data["GUI"]["theme"] = mw_themes;
data["GUI"]["iconSize"] = m_icon_size;
@ -504,7 +516,11 @@ void setDefaultValues() {
shouldDumpPM4 = false;
vblankDivider = 1;
vkValidation = false;
vkValidationSync = false;
vkValidationGpu = false;
rdocEnable = false;
vkMarkers = false;
vkCrashDiagnostic = false;
emulator_language = "en";
m_language = 1;
gpuId = -1;

View file

@ -31,7 +31,6 @@ bool copyGPUCmdBuffers();
bool dumpShaders();
bool dumpPM4();
bool isRdocEnabled();
bool isMarkersEnabled();
u32 vblankDiv();
void setDebugDump(bool enable);
@ -62,6 +61,8 @@ void setRdocEnabled(bool enable);
bool vkValidationEnabled();
bool vkValidationSyncEnabled();
bool vkValidationGpuEnabled();
bool vkMarkersEnabled();
bool vkCrashDiagnosticEnabled();
// Gui
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);

View file

@ -499,7 +499,7 @@ int PS4_SYSV_ABI sceGnmDestroyWorkloadStream() {
}
void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) {
LOG_INFO(Lib_GnmDriver, "vqid {}, offset_dw {}", gnm_vqid, next_offs_dw);
LOG_DEBUG(Lib_GnmDriver, "vqid {}, offset_dw {}", gnm_vqid, next_offs_dw);
if (gnm_vqid == 0) {
return;
@ -2054,7 +2054,7 @@ s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, u32* dcb_gpu_addrs
u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes, u32 vo_handle,
u32 buf_idx, u32 flip_mode, u32 flip_arg) {
LOG_INFO(Lib_GnmDriver, "called [buf = {}]", buf_idx);
LOG_DEBUG(Lib_GnmDriver, "called [buf = {}]", buf_idx);
auto* cmdbuf = dcb_gpu_addrs[count - 1];
const auto size_dw = dcb_sizes_in_bytes[count - 1] / 4;
@ -2078,7 +2078,7 @@ int PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffersForWorkload() {
s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[],
u32* dcb_sizes_in_bytes, const u32* ccb_gpu_addrs[],
u32* ccb_sizes_in_bytes) {
LOG_INFO(Lib_GnmDriver, "called");
LOG_DEBUG(Lib_GnmDriver, "called");
if (!dcb_gpu_addrs || !dcb_sizes_in_bytes) {
LOG_ERROR(Lib_GnmDriver, "dcbGpuAddrs and dcbSizesInBytes must not be NULL");
@ -2154,7 +2154,7 @@ int PS4_SYSV_ABI sceGnmSubmitCommandBuffersForWorkload() {
}
int PS4_SYSV_ABI sceGnmSubmitDone() {
LOG_INFO(Lib_GnmDriver, "called");
LOG_DEBUG(Lib_GnmDriver, "called");
if (!liverpool->IsGpuIdle()) {
submission_lock = true;
}

View file

@ -565,7 +565,7 @@ int PS4_SYSV_ABI sceUserServiceGetLoginFlag() {
}
s32 PS4_SYSV_ABI sceUserServiceGetLoginUserIdList(OrbisUserServiceLoginUserIdList* userIdList) {
LOG_INFO(Lib_UserService, "called");
LOG_DEBUG(Lib_UserService, "called");
if (userIdList == nullptr) {
LOG_ERROR(Lib_UserService, "user_id is null");
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;

View file

@ -140,8 +140,8 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode
return ORBIS_VIDEO_OUT_ERROR_INVALID_INDEX;
}
LOG_INFO(Lib_VideoOut, "bufferIndex = {}, flipMode = {}, flipArg = {}", bufferIndex, flipMode,
flipArg);
LOG_DEBUG(Lib_VideoOut, "bufferIndex = {}, flipMode = {}, flipArg = {}", bufferIndex, flipMode,
flipArg);
if (!driver->SubmitFlip(port, bufferIndex, flipArg)) {
LOG_ERROR(Lib_VideoOut, "Flip queue is full");

View file

@ -64,7 +64,8 @@ Emulator::Emulator() {
LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled());
LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled());
LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled());
LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::isMarkersEnabled());
LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::vkMarkersEnabled());
LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::vkCrashDiagnosticEnabled());
// Defer until after logging is initialized.
memory = Core::Memory::Instance();

View file

@ -347,7 +347,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
if (rasterizer) {
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->Draw(true);
rasterizer->ScopeMarkerEnd();
}
@ -363,7 +362,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(
fmt::format("dcb:{}:DrawIndexOffset2", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->Draw(true, draw_index_off->index_offset);
rasterizer->ScopeMarkerEnd();
}
@ -376,7 +374,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
if (rasterizer) {
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->Draw(false);
rasterizer->ScopeMarkerEnd();
}
@ -390,7 +387,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
if (rasterizer) {
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndirect", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->DrawIndirect(false, ib_address, offset, size);
rasterizer->ScopeMarkerEnd();
}
@ -406,7 +402,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(
fmt::format("dcb:{}:DrawIndexIndirect", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->DrawIndirect(true, ib_address, offset, size);
rasterizer->ScopeMarkerEnd();
}
@ -421,7 +416,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->DispatchDirect();
rasterizer->ScopeMarkerEnd();
}
@ -437,7 +431,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(
fmt::format("dcb:{}:DispatchIndirect", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->DispatchIndirect(ib_address, offset, size);
rasterizer->ScopeMarkerEnd();
}
@ -602,7 +595,6 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, int vqid) {
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address));
rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->DispatchDirect();
rasterizer->ScopeMarkerEnd();
}

View file

@ -68,8 +68,10 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for
RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_)
: window{window_}, liverpool{liverpool_},
instance{window, Config::getGpuId(), Config::vkValidationEnabled()}, draw_scheduler{instance},
present_scheduler{instance}, flip_scheduler{instance}, swapchain{instance, window},
instance{window, Config::getGpuId(), Config::vkValidationEnabled(),
Config::vkCrashDiagnosticEnabled()},
draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance},
swapchain{instance, window},
rasterizer{std::make_unique<Rasterizer>(instance, draw_scheduler, liverpool)},
texture_cache{rasterizer->GetTextureCache()} {
const u32 num_images = swapchain.GetImageCount();
@ -357,7 +359,7 @@ Frame* RendererVulkan::GetRenderFrame() {
{
std::unique_lock lock{free_mutex};
free_cv.wait(lock, [this] { return !free_queue.empty(); });
LOG_INFO(Render_Vulkan, "Got render frame, remaining {}", free_queue.size() - 1);
LOG_DEBUG(Render_Vulkan, "Got render frame, remaining {}", free_queue.size() - 1);
// Take the frame from the queue
frame = free_queue.front();

View file

@ -49,14 +49,15 @@ std::string GetReadableVersion(u32 version) {
} // Anonymous namespace
Instance::Instance(bool enable_validation, bool dump_command_buffers)
Instance::Instance(bool enable_validation, bool enable_crash_diagnostic)
: instance{CreateInstance(Frontend::WindowSystemType::Headless, enable_validation,
dump_command_buffers)},
enable_crash_diagnostic)},
physical_devices{instance->enumeratePhysicalDevices()} {}
Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index,
bool enable_validation /*= false*/)
: instance{CreateInstance(window.getWindowInfo().type, enable_validation, false)},
bool enable_validation /*= false*/, bool enable_crash_diagnostic /*= false*/)
: instance{CreateInstance(window.getWindowInfo().type, enable_validation,
enable_crash_diagnostic)},
physical_devices{instance->enumeratePhysicalDevices()} {
if (enable_validation) {
debug_callback = CreateDebugCallback(*instance);
@ -228,13 +229,6 @@ bool Instance::CreateDevice() {
add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
if (Config::isMarkersEnabled()) {
const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
if (has_sync2) {
has_nv_checkpoints = add_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME);
}
}
#ifdef __APPLE__
// Required by Vulkan spec if supported.
add_extension(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);

View file

@ -21,9 +21,9 @@ namespace Vulkan {
class Instance {
public:
explicit Instance(bool validation = false, bool dump_command_buffers = false);
explicit Instance(bool validation = false, bool crash_diagnostic = false);
explicit Instance(Frontend::WindowSDL& window, s32 physical_device_index,
bool enable_validation = false);
bool enable_validation = false, bool enable_crash_diagnostic = false);
~Instance();
/// Returns a formatted string for the driver version
@ -82,10 +82,6 @@ public:
return profiler_context;
}
bool HasNvCheckpoints() const {
return has_nv_checkpoints;
}
/// Returns true when a known debugging tool is attached.
bool HasDebuggingToolAttached() const {
return has_renderdoc || has_nsight_graphics;
@ -270,7 +266,6 @@ private:
bool debug_utils_supported{};
bool has_nsight_graphics{};
bool has_renderdoc{};
bool has_nv_checkpoints{};
};
} // namespace Vulkan

View file

@ -17,6 +17,7 @@
#include "common/assert.h"
#include "common/config.h"
#include "common/logging/log.h"
#include "common/path_util.h"
#include "sdl_window.h"
#include "video_core/renderer_vulkan/vk_platform.h"
@ -32,7 +33,7 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instan
namespace Vulkan {
static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
static const char* const API_DUMP_LAYER_NAME = "VK_LAYER_LUNARG_api_dump";
static const char* const CRASH_DIAGNOSTIC_LAYER_NAME = "VK_LAYER_LUNARG_crash_diagnostic";
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type,
@ -196,7 +197,7 @@ std::vector<const char*> GetInstanceExtensions(Frontend::WindowSystemType window
}
vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation,
bool dump_command_buffers) {
bool enable_crash_diagnostic) {
LOG_INFO(Render_Vulkan, "Creating vulkan instance");
#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL
@ -227,15 +228,23 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
u32 num_layers = 0;
std::array<const char*, 2> layers;
vk::Bool32 enable_force_barriers = vk::False;
const char* log_path{};
#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL
if (enable_validation) {
layers[num_layers++] = VALIDATION_LAYER_NAME;
}
if (dump_command_buffers) {
layers[num_layers++] = API_DUMP_LAYER_NAME;
if (enable_crash_diagnostic) {
layers[num_layers++] = CRASH_DIAGNOSTIC_LAYER_NAME;
static const auto crash_diagnostic_path =
Common::FS::GetUserPathString(Common::FS::PathType::LogDir);
log_path = crash_diagnostic_path.c_str();
enable_force_barriers = vk::True;
}
#else
if (enable_validation || dump_command_buffers) {
if (enable_validation || enable_crash_diagnostic) {
LOG_WARNING(Render_Vulkan,
"Skipping loading Vulkan layers as dynamic loading is not enabled.");
}
@ -258,7 +267,7 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
},
vk::LayerSettingEXT{
.pLayerName = VALIDATION_LAYER_NAME,
.pSettingName = "sync_queue_submit",
.pSettingName = "syncval_submit_time_validation",
.type = vk::LayerSettingTypeEXT::eBool32,
.valueCount = 1,
.pValues = &enable_sync,
@ -298,6 +307,20 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
.valueCount = 1,
.pValues = &enable_gpuav,
},
vk::LayerSettingEXT{
.pLayerName = "lunarg_crash_diagnostic",
.pSettingName = "output_path",
.type = vk::LayerSettingTypeEXT::eString,
.valueCount = 1,
.pValues = &log_path,
},
vk::LayerSettingEXT{
.pLayerName = "lunarg_crash_diagnostic",
.pSettingName = "sync_after_commands",
.type = vk::LayerSettingTypeEXT::eBool32,
.valueCount = 1,
.pValues = &enable_force_barriers,
},
};
vk::StructureChain<vk::InstanceCreateInfo, vk::LayerSettingsCreateInfoEXT> instance_ci_chain = {

View file

@ -22,7 +22,7 @@ constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2;
vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window);
vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation,
bool dump_command_buffers);
bool enable_crash_diagnostic);
vk::UniqueDebugUtilsMessengerEXT CreateDebugCallback(vk::Instance instance);

View file

@ -321,7 +321,7 @@ void Rasterizer::UpdateDepthStencilState() {
}
void Rasterizer::ScopeMarkerBegin(const std::string_view& str) {
if (Config::nullGpu() || !Config::isMarkersEnabled()) {
if (Config::nullGpu() || !Config::vkMarkersEnabled()) {
return;
}
@ -332,7 +332,7 @@ void Rasterizer::ScopeMarkerBegin(const std::string_view& str) {
}
void Rasterizer::ScopeMarkerEnd() {
if (Config::nullGpu() || !Config::isMarkersEnabled()) {
if (Config::nullGpu() || !Config::vkMarkersEnabled()) {
return;
}
@ -341,7 +341,7 @@ void Rasterizer::ScopeMarkerEnd() {
}
void Rasterizer::ScopedMarkerInsert(const std::string_view& str) {
if (Config::nullGpu() || !Config::isMarkersEnabled()) {
if (Config::nullGpu() || !Config::vkMarkersEnabled()) {
return;
}
@ -351,11 +351,4 @@ void Rasterizer::ScopedMarkerInsert(const std::string_view& str) {
});
}
void Rasterizer::Breadcrumb(u64 id) {
if (Config::nullGpu() || !instance.HasNvCheckpoints()) {
return;
}
scheduler.CommandBuffer().setCheckpointNV(id);
}
} // namespace Vulkan

View file

@ -40,7 +40,6 @@ public:
void ScopeMarkerBegin(const std::string_view& str);
void ScopeMarkerEnd();
void ScopedMarkerInsert(const std::string_view& str);
void Breadcrumb(u64 id);
void InvalidateMemory(VAddr addr, u64 size);
void MapMemory(VAddr addr, u64 size);

View file

@ -192,13 +192,6 @@ void Scheduler::SubmitExecution(SubmitInfo& info) {
try {
instance.GetGraphicsQueue().submit(submit_info, info.fence);
} catch (vk::DeviceLostError& err) {
if (instance.HasNvCheckpoints()) {
const auto checkpoint_data = instance.GetGraphicsQueue().getCheckpointData2NV();
for (const auto& cp : checkpoint_data) {
LOG_CRITICAL(Render_Vulkan, "{}: {:#x}", vk::to_string(cp.stage),
reinterpret_cast<u64>(cp.pCheckpointMarker));
}
}
UNREACHABLE_MSG("Device lost during submit: {}", err.what());
}

View file

@ -2,12 +2,10 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
#include "common/config.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/texture_cache/image.h"
#include "video_core/texture_cache/tile_manager.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnullability-completeness"
@ -17,7 +15,6 @@
namespace VideoCore {
using namespace Vulkan;
using Libraries::VideoOut::TilingMode;
bool ImageInfo::IsBlockCoded() const {
switch (pixel_format) {