mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-06-27 03:26:17 +02:00
[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:
parent
8118557c17
commit
6637810fe6
31 changed files with 1669 additions and 17 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue