[android] gpu logs functions (#3389)

Since Android is a pain when it comes to checking GPU logs in more depth, this is a better way to see what's going on, especially for testers...

This should be expanded to Mali, Xclipse, and Tensor in the future. Since I don't own any of these devices, it's up to developers with similar capabilities to add support for this system.

~~The GPU log sharing button should also be added in the future... For now, they are available in the same location as the traditional logs.~~ Added on 572810e022

Co-authored-by: DraVee <dravee@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3389
Reviewed-by: DraVee <dravee@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: MrPurple666 <antoniosacramento666usa@gmail.com>
Co-committed-by: MrPurple666 <antoniosacramento666usa@gmail.com>
This commit is contained in:
MrPurple666 2026-02-01 02:02:23 +01:00 committed by crueter
parent 8118557c17
commit 6637810fe6
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
31 changed files with 1669 additions and 17 deletions

View file

@ -1,12 +1,26 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <string_view>
#include "common/logging/log.h"
#include "common/settings.h"
#include "video_core/vulkan_common/vulkan_debug_callback.h"
#include "video_core/gpu_logging/gpu_logging.h"
namespace Vulkan {
namespace {
// Helper to get message type as string for GPU logging
const char* GetMessageTypeName(VkDebugUtilsMessageTypeFlagsEXT type) {
if (type & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
return "Validation";
} else if (type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
return "Performance";
} else {
return "General";
}
}
VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT type,
const VkDebugUtilsMessengerCallbackDataEXT* data,
@ -60,6 +74,28 @@ VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
} else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
LOG_DEBUG(Render_Vulkan, "{}", message);
}
// Route to GPU logger for tracking Vulkan validation messages
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
// Convert severity to result code for logging (negative = error)
int result_code = 0;
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
result_code = -1;
} else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
result_code = -2;
}
// Get message ID name or use generic name
const char* call_name = data->pMessageIdName ? data->pMessageIdName : "VulkanDebug";
GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
call_name,
std::string(GetMessageTypeName(type)) + ": " + std::string(message),
result_code
);
}
return VK_FALSE;
}

View file

@ -13,6 +13,8 @@
#include <utility>
#include <vector>
#include <fmt/format.h>
#include "common/assert.h"
#include "common/literals.h"
#include <ranges>
@ -22,6 +24,7 @@
#include "video_core/vulkan_common/vma.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/gpu_logging/gpu_logging.h"
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
#include <adrenotools/bcenabler.h>
@ -734,9 +737,13 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
};
vk::Check(vmaCreateAllocator(&allocator_info, &allocator));
// Initialize GPU logging if enabled
InitializeGPULogging();
}
Device::~Device() {
ShutdownGPULogging();
vmaDestroyAllocator(allocator);
}
@ -1622,4 +1629,106 @@ std::vector<VkDeviceQueueCreateInfo> Device::GetDeviceQueueCreateInfos() const {
return queue_cis;
}
void Device::InitializeGPULogging() {
if (!Settings::values.gpu_logging_enabled.GetValue()) {
return;
}
// Detect driver type
const auto driver_id = GetDriverID();
GPU::Logging::DriverType detected_driver = GPU::Logging::DriverType::Unknown;
if (driver_id == VK_DRIVER_ID_MESA_TURNIP) {
detected_driver = GPU::Logging::DriverType::Turnip;
} else if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
detected_driver = GPU::Logging::DriverType::Qualcomm;
}
// Get log level from settings
const auto log_level = static_cast<GPU::Logging::LogLevel>(
static_cast<u32>(Settings::values.gpu_log_level.GetValue()));
// Initialize GPU logger
GPU::Logging::GPULogger::GetInstance().Initialize(log_level, detected_driver);
// Configure feature flags
GPU::Logging::GPULogger::GetInstance().EnableVulkanCallTracking(
Settings::values.gpu_log_vulkan_calls.GetValue());
GPU::Logging::GPULogger::GetInstance().EnableShaderDumps(
Settings::values.gpu_log_shader_dumps.GetValue());
GPU::Logging::GPULogger::GetInstance().EnableMemoryTracking(
Settings::values.gpu_log_memory_tracking.GetValue());
GPU::Logging::GPULogger::GetInstance().EnableDriverDebugInfo(
Settings::values.gpu_log_driver_debug.GetValue());
GPU::Logging::GPULogger::GetInstance().SetRingBufferSize(
Settings::values.gpu_log_ring_buffer_size.GetValue());
// Log comprehensive driver and extension information
if (Settings::values.gpu_log_driver_debug.GetValue()) {
std::string driver_info;
// Device information
const auto& props = properties.properties;
driver_info += fmt::format("Device: {}\n", props.deviceName);
driver_info += fmt::format("Driver Name: {}\n", properties.driver.driverName);
driver_info += fmt::format("Driver Info: {}\n", properties.driver.driverInfo);
// Version information
const u32 driver_version = props.driverVersion;
const u32 api_version = props.apiVersion;
driver_info += fmt::format("Driver Version: {}.{}.{}\n",
VK_API_VERSION_MAJOR(driver_version),
VK_API_VERSION_MINOR(driver_version),
VK_API_VERSION_PATCH(driver_version));
driver_info += fmt::format("Vulkan API Version: {}.{}.{}\n",
VK_API_VERSION_MAJOR(api_version),
VK_API_VERSION_MINOR(api_version),
VK_API_VERSION_PATCH(api_version));
driver_info += fmt::format("Driver ID: {}\n", static_cast<u32>(driver_id));
// Vendor and device IDs
driver_info += fmt::format("Vendor ID: 0x{:04X}\n", props.vendorID);
driver_info += fmt::format("Device ID: 0x{:04X}\n", props.deviceID);
// Extensions - separate QCOM extensions from others
driver_info += "\n=== Loaded Vulkan Extensions ===\n";
std::vector<std::string> qcom_exts;
std::vector<std::string> other_exts;
for (const auto& ext : loaded_extensions) {
if (ext.find("QCOM") != std::string::npos || ext.find("qcom") != std::string::npos) {
qcom_exts.push_back(ext);
} else {
other_exts.push_back(ext);
}
}
// Log QCOM extensions first
if (!qcom_exts.empty()) {
driver_info += "\nQualcomm Proprietary Extensions:\n";
for (const auto& ext : qcom_exts) {
driver_info += fmt::format(" - {}\n", ext);
}
}
// Log other extensions
if (!other_exts.empty()) {
driver_info += "\nStandard Extensions:\n";
for (const auto& ext : other_exts) {
driver_info += fmt::format(" - {}\n", ext);
}
}
driver_info += fmt::format("\nTotal Extensions Loaded: {}\n", loaded_extensions.size());
GPU::Logging::GPULogger::GetInstance().LogDriverDebugInfo(driver_info);
}
}
void Device::ShutdownGPULogging() {
if (GPU::Logging::GPULogger::GetInstance().IsInitialized()) {
GPU::Logging::GPULogger::GetInstance().Shutdown();
}
}
} // namespace Vulkan

View file

@ -929,6 +929,10 @@ public:
return nvidia_arch;
}
/// GPU logging integration
void InitializeGPULogging();
void ShutdownGPULogging();
private:
/// Checks if the physical device is suitable and configures the object state
/// with all necessary info about its properties.

View file

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@ -22,6 +22,8 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "common/settings.h"
namespace Vulkan {
namespace {
@ -107,7 +109,17 @@ namespace Vulkan {
MemoryCommit::MemoryCommit(VmaAllocator alloc, VmaAllocation a,
const VmaAllocationInfo &info) noexcept
: allocator{alloc}, allocation{a}, memory{info.deviceMemory},
offset{info.offset}, size{info.size}, mapped_ptr{info.pMappedData} {}
offset{info.offset}, size{info.size}, mapped_ptr{info.pMappedData} {
// Log GPU memory allocation
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_memory_tracking.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogMemoryAllocation(
reinterpret_cast<uintptr_t>(memory),
static_cast<u64>(size),
0 // Memory property flags (not easily available from VMA)
);
}
}
MemoryCommit::~MemoryCommit() { Release(); }
@ -166,6 +178,15 @@ namespace Vulkan {
void MemoryCommit::Release() {
if (allocation && allocator) {
// Log GPU memory deallocation
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_memory_tracking.GetValue() &&
memory != VK_NULL_HANDLE) {
GPU::Logging::GPULogger::GetInstance().LogMemoryDeallocation(
reinterpret_cast<uintptr_t>(memory)
);
}
if (mapped_ptr) {
vmaUnmapMemory(allocator, allocation);
mapped_ptr = nullptr;
@ -218,7 +239,19 @@ namespace Vulkan {
VkImage handle{};
VmaAllocation allocation{};
vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, nullptr));
VmaAllocationInfo alloc_info{};
vk::Check(vmaCreateImage(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info));
// Log GPU memory allocation for images
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_memory_tracking.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogMemoryAllocation(
reinterpret_cast<uintptr_t>(alloc_info.deviceMemory),
static_cast<u64>(alloc_info.size),
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
);
}
return vk::Image(handle, ci.usage, *device.GetLogical(), allocator, allocation,
device.GetDispatchLoader());
}
@ -245,6 +278,16 @@ namespace Vulkan {
vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info));
vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags);
// Log GPU memory allocation for buffers
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_memory_tracking.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogMemoryAllocation(
reinterpret_cast<uintptr_t>(alloc_info.deviceMemory),
static_cast<u64>(alloc_info.size),
property_flags
);
}
u8 *data = reinterpret_cast<u8 *>(alloc_info.pMappedData);
const std::span<u8> mapped_data = data ? std::span<u8>{data, ci.size} : std::span<u8>{};
const bool is_coherent = (property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0;