[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,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 2019 yuzu Emulator Project
@ -8,6 +8,7 @@
#include <vector>
#include <boost/container/small_vector.hpp>
#include <fmt/format.h>
#include "video_core/renderer_vulkan/pipeline_helper.h"
#include "video_core/renderer_vulkan/pipeline_statistics.h"
@ -20,6 +21,8 @@
#include "video_core/shader_notify.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"
#include "common/settings.h"
namespace Vulkan {
@ -82,6 +85,13 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
},
*pipeline_cache);
// Log compute pipeline creation
if (Settings::values.gpu_logging_enabled.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogPipelineStateChange(
"ComputePipeline created"
);
}
if (pipeline_statistics) {
pipeline_statistics->Collect(*pipeline);
}
@ -207,6 +217,13 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
build_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
});
}
// Log compute pipeline binding
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogPipelineBind(true, "compute pipeline");
}
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
const bool is_rescaling = !info.texture_descriptors.empty() || !info.image_descriptors.empty();
scheduler.Record([this, descriptor_data, is_rescaling,

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 2021 yuzu Emulator Project
@ -10,6 +10,7 @@
#include <boost/container/small_vector.hpp>
#include <boost/container/static_vector.hpp>
#include <fmt/format.h>
#include "video_core/renderer_vulkan/pipeline_helper.h"
@ -25,6 +26,8 @@
#include "video_core/shader_notify.h"
#include "video_core/texture_cache/texture_cache.h"
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "common/settings.h"
#if defined(_MSC_VER) && defined(NDEBUG)
#define LAMBDA_FORCEINLINE [[msvc::forceinline]]
@ -513,6 +516,14 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
const bool is_rescaling{texture_cache.IsRescaling()};
const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
// Log graphics pipeline binding
if (bind_pipeline && Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string pipeline_info = fmt::format("hash=0x{:016x}", key.Hash());
GPU::Logging::GPULogger::GetInstance().LogPipelineBind(false, pipeline_info);
}
const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
is_rescaling, update_rescaling,
@ -954,6 +965,16 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
.basePipelineIndex = 0,
},
*pipeline_cache);
// Log graphics pipeline creation
if (Settings::values.gpu_logging_enabled.GetValue()) {
const std::string pipeline_info = fmt::format(
"GraphicsPipeline created: stages={}, attachments={}",
shader_stages.size(),
color_blend_ci.attachmentCount
);
GPU::Logging::GPULogger::GetInstance().LogPipelineStateChange(pipeline_info);
}
}
void GraphicsPipeline::Validate() {

View file

@ -9,6 +9,7 @@
#include <fstream>
#include <iostream>
#include <memory>
#include <span>
#include <thread>
#include <vector>
#include <bit>
@ -42,6 +43,7 @@
#include "video_core/surface.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"
namespace Vulkan {
@ -724,6 +726,17 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
const std::vector<u32> code{EmitSPIRV(profile, runtime_info, program, binding, this->optimize_spirv_output)};
device.SaveShader(code);
modules[stage_index] = BuildShader(device, code);
// Log shader compilation to GPU logger (with SPIR-V binary dump if enabled)
if (Settings::values.gpu_logging_enabled.GetValue()) {
static constexpr std::array stage_names{"vertex", "tess_control", "tess_eval", "geometry", "fragment"};
const std::string shader_name = fmt::format("shader_{:016x}_{}", key.unique_hashes[index], stage_names[stage_index]);
const std::string shader_info = fmt::format("SPIR-V size: {} bytes, hash: {:016x}",
code.size() * sizeof(u32), key.unique_hashes[index]);
GPU::Logging::GPULogger::GetInstance().LogShaderCompilation(shader_name, shader_info,
std::span<const u32>(code.data(), code.size()));
}
if (device.HasDebuggingToolAttached()) {
const std::string name{fmt::format("Shader {:016x}", key.unique_hashes[index])};
modules[stage_index].SetObjectNameEXT(name.c_str());
@ -831,6 +844,16 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
const std::vector<u32> code{EmitSPIRV(profile, program, this->optimize_spirv_output)};
device.SaveShader(code);
vk::ShaderModule spv_module{BuildShader(device, code)};
// Log compute shader compilation to GPU logger (with SPIR-V binary dump if enabled)
if (Settings::values.gpu_logging_enabled.GetValue()) {
const std::string shader_name = fmt::format("shader_{:016x}_compute", key.unique_hash);
const std::string shader_info = fmt::format("SPIR-V size: {} bytes, hash: {:016x}",
code.size() * sizeof(u32), key.unique_hash);
GPU::Logging::GPULogger::GetInstance().LogShaderCompilation(shader_name, shader_info,
std::span<const u32>(code.data(), code.size()));
}
if (device.HasDebuggingToolAttached()) {
const auto name{fmt::format("Shader {:016x}", key.unique_hash)};
spv_module.SetObjectNameEXT(name.c_str());

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 2019 yuzu Emulator Project
@ -9,6 +9,8 @@
#include <memory>
#include <mutex>
#include <fmt/format.h>
#include "video_core/renderer_vulkan/renderer_vulkan.h"
#include "common/assert.h"
@ -16,6 +18,7 @@
#include "common/scope_exit.h"
#include "common/settings.h"
#include "video_core/buffer_cache/buffer_cache.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "video_core/control/channel_state.h"
#include "video_core/engines/draw_manager.h"
#include "video_core/engines/kepler_compute.h"
@ -277,6 +280,20 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
}
});
}
// Log draw call
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string params = is_indexed ?
fmt::format("vertices={}, instances={}, firstIndex={}, baseVertex={}, baseInstance={}",
draw_params.num_vertices, draw_params.num_instances,
draw_params.first_index, draw_params.base_vertex, draw_params.base_instance) :
fmt::format("vertices={}, instances={}, firstVertex={}, firstInstance={}",
draw_params.num_vertices, draw_params.num_instances,
draw_params.base_vertex, draw_params.base_instance);
GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
is_indexed ? "vkCmdDrawIndexed" : "vkCmdDraw", params, VK_SUCCESS);
}
});
}
@ -324,6 +341,16 @@ void RasterizerVulkan::DrawIndirect() {
static_cast<u32>(params.stride));
}
});
// Log indirect draw call
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string log_params = fmt::format("drawCount={}, stride={}",
params.max_draw_counts, params.stride);
GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
params.is_indexed ? "vkCmdDrawIndexedIndirect" : "vkCmdDrawIndirect",
log_params, VK_SUCCESS);
}
});
buffer_cache.SetDrawIndirect(nullptr);
}
@ -568,6 +595,15 @@ void RasterizerVulkan::DispatchCompute() {
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, READ_BARRIER); });
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
// Log compute dispatch
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string params = fmt::format("groupCountX={}, groupCountY={}, groupCountZ={}",
dim[0], dim[1], dim[2]);
GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
"vkCmdDispatch", params, VK_SUCCESS);
}
}
void RasterizerVulkan::ResetCounter(VideoCommon::QueryType type) {
@ -1066,6 +1102,11 @@ void RasterizerVulkan::HandleTransformFeedback() {
query_cache.CounterEnable(VideoCommon::QueryType::StreamingByteCount,
regs.transform_feedback_enabled);
if (regs.transform_feedback_enabled != 0) {
// Log extension usage for transform feedback
if (Settings::values.gpu_logging_enabled.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
"VK_EXT_transform_feedback", "HandleTransformFeedback");
}
UNIMPLEMENTED_IF(regs.IsShaderConfigEnabled(Maxwell::ShaderType::TessellationInit) ||
regs.IsShaderConfigEnabled(Maxwell::ShaderType::Tessellation));
}

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 2019 yuzu Emulator Project
@ -9,9 +9,13 @@
#include <thread>
#include <utility>
#include <fmt/format.h>
#include "video_core/renderer_vulkan/vk_query_cache.h"
#include "common/settings.h"
#include "common/thread.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "video_core/renderer_vulkan/vk_command_pool.h"
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
@ -114,6 +118,15 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
state.framebuffer = framebuffer_handle;
state.render_area = render_area;
// Log render pass begin
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
const std::string render_pass_info = fmt::format(
"renderArea={}x{}, numImages={}",
render_area.width, render_area.height, framebuffer->NumImages());
GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info);
}
Record([renderpass, framebuffer_handle, render_area](vk::CommandBuffer cmdbuf) {
const VkRenderPassBeginInfo renderpass_bi{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
@ -270,6 +283,12 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
switch (const VkResult result = master_semaphore->SubmitQueue(
cmdbuf, upload_cmdbuf, signal_semaphore, wait_semaphore, signal_value)) {
case VK_SUCCESS:
// Log successful queue submission
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogVulkanCall(
"vkQueueSubmit", "", VK_SUCCESS);
}
break;
case VK_ERROR_DEVICE_LOST:
device.ReportLoss();
@ -305,6 +324,12 @@ void Scheduler::EndRenderPass()
return;
}
// Log render pass end
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogRenderPassEnd();
}
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
query_cache->NotifySegment(false);

View file

@ -16,6 +16,7 @@
#include "common/settings.h"
#include "video_core/renderer_vulkan/vk_texture_cache.h"
#include "video_core/gpu_logging/gpu_logging.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/renderer_vulkan/blit_image.h"
@ -2304,6 +2305,11 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
const void* pnext = nullptr;
if (has_custom_border_colors) {
pnext = &border_ci;
// Log extension usage for custom border color
if (Settings::values.gpu_logging_enabled.GetValue()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
"VK_EXT_custom_border_color", "Sampler::Sampler");
}
}
const VkSamplerReductionModeCreateInfoEXT reduction_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,