aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/gpu_logging
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/gpu_logging')
-rw-r--r--src/video_core/gpu_logging/gpu_logging.cpp62
-rw-r--r--src/video_core/gpu_logging/gpu_logging.h12
2 files changed, 33 insertions, 41 deletions
diff --git a/src/video_core/gpu_logging/gpu_logging.cpp b/src/video_core/gpu_logging/gpu_logging.cpp
index 5f5e376e99..72e48e4996 100644
--- a/src/video_core/gpu_logging/gpu_logging.cpp
+++ b/src/video_core/gpu_logging/gpu_logging.cpp
@@ -4,6 +4,7 @@
#include "video_core/gpu_logging/gpu_logging.h"
#include <fmt/format.h>
+#include <mutex>
#include <thread>
#include "common/fs/file.h"
@@ -280,13 +281,12 @@ void GPULogger::LogMemoryDeallocation(uintptr_t memory) {
}
void GPULogger::LogShaderCompilation(const std::string& shader_name,
- const std::string& shader_info,
- std::span<const u32> spirv_code) {
+ const std::string& shader_info) {
if (!initialized || current_level == LogLevel::Off) {
return;
}
- if (!dump_shaders && current_level < LogLevel::Verbose) {
+ if (current_level < LogLevel::Verbose) {
return;
}
@@ -294,38 +294,36 @@ void GPULogger::LogShaderCompilation(const std::string& shader_name,
std::chrono::steady_clock::now().time_since_epoch());
const auto log_entry = fmt::format("[{}] [Shader] Compiled: {} ({})\n",
- FormatTimestamp(timestamp), shader_name, shader_info);
+ FormatTimestamp(timestamp), shader_name, shader_info);
WriteToLog(log_entry);
+}
- // Dump SPIR-V binary if enabled and we have data
- if (dump_shaders && !spirv_code.empty()) {
- using namespace Common::FS;
- const auto& log_dir = GetEdenPath(EdenPath::LogDir);
- const auto shaders_dir = log_dir / "shaders";
+bool IsActive() noexcept {
+ return Settings::values.gpu_log_level.GetValue() != Settings::GpuLogLevel::Off;
+}
- // Create directory on first dump
- if (!shader_dump_dir_created) {
- [[maybe_unused]] const bool created = CreateDir(shaders_dir);
- shader_dump_dir_created = true;
- }
+void DumpSpirvShader(u64 shader_hash, std::span<const u32> spirv_code) {
+ if (spirv_code.empty()) {
+ return;
+ }
- // Write SPIR-V binary file
- const auto shader_path = shaders_dir / fmt::format("{}.spv", shader_name);
- auto shader_file = std::make_unique<Common::FS::IOFile>(
- shader_path, FileAccessMode::Write, FileType::BinaryFile);
-
- if (shader_file->IsOpen()) {
- const size_t bytes_to_write = spirv_code.size() * sizeof(u32);
- static_cast<void>(shader_file->WriteSpan(spirv_code));
- shader_file->Close();
-
- const auto dump_log = fmt::format("[{}] [Shader] Dumped SPIR-V: {} ({} bytes)\n",
- FormatTimestamp(timestamp), shader_path.string(), bytes_to_write);
- WriteToLog(dump_log);
- } else {
- LOG_WARNING(Render_Vulkan, "[GPU Logging] Failed to dump shader: {}", shader_path.string());
- }
+ using namespace Common::FS;
+ const auto& dump_dir = GetEdenPath(EdenPath::DumpDir);
+
+ // Ensure DumpDir exists once. CreateDir is idempotent, so guarded to skip the syscall.
+ static std::once_flag dump_dir_flag;
+ std::call_once(dump_dir_flag, [&dump_dir]() {
+ [[maybe_unused]] const bool created = CreateDir(dump_dir);
+ });
+
+ const auto shader_path = dump_dir / fmt::format("{:016x}_{:016x}.spv",
+ Settings::GetCurrentProgramID(), shader_hash);
+ Common::FS::IOFile shader_file(shader_path, FileAccessMode::Write, FileType::BinaryFile);
+ if (!shader_file.IsOpen()) {
+ LOG_WARNING(Render_Vulkan, "[Shader Dump] Failed to open {}", shader_path.string());
+ return;
}
+ static_cast<void>(shader_file.WriteSpan(spirv_code));
}
void GPULogger::LogPipelineStateChange(const std::string& state_info) {
@@ -657,10 +655,6 @@ void GPULogger::EnableVulkanCallTracking(bool enabled) {
track_vulkan_calls = enabled;
}
-void GPULogger::EnableShaderDumps(bool enabled) {
- dump_shaders = enabled;
-}
-
void GPULogger::EnableMemoryTracking(bool enabled) {
track_memory = enabled;
}
diff --git a/src/video_core/gpu_logging/gpu_logging.h b/src/video_core/gpu_logging/gpu_logging.h
index 134fa94c0f..b16988ed0b 100644
--- a/src/video_core/gpu_logging/gpu_logging.h
+++ b/src/video_core/gpu_logging/gpu_logging.h
@@ -87,8 +87,7 @@ public:
void LogVulkanCall(const std::string& call_name, const std::string& params, int result);
void LogMemoryAllocation(uintptr_t memory, u64 size, u32 memory_flags);
void LogMemoryDeallocation(uintptr_t memory);
- void LogShaderCompilation(const std::string& shader_name, const std::string& shader_info,
- std::span<const u32> spirv_code = {});
+ void LogShaderCompilation(const std::string& shader_name, const std::string& shader_info);
void LogPipelineStateChange(const std::string& state_info);
void LogDriverDebugInfo(const std::string& debug_info);
@@ -121,7 +120,6 @@ public:
// Settings
void SetLogLevel(LogLevel level);
void EnableVulkanCallTracking(bool enabled);
- void EnableShaderDumps(bool enabled);
void EnableMemoryTracking(bool enabled);
void EnableDriverDebugInfo(bool enabled);
void SetRingBufferSize(size_t entries);
@@ -171,7 +169,6 @@ private:
// Feature flags
bool track_vulkan_calls = true;
- bool dump_shaders = false;
bool track_memory = false;
bool capture_driver_debug = false;
@@ -179,15 +176,16 @@ private:
std::set<std::string> used_extensions;
mutable std::mutex extension_mutex;
- // Shader dump directory (created on demand)
- bool shader_dump_dir_created = false;
-
// Stored state for crash dumps
std::string stored_driver_debug_info;
std::string stored_pipeline_state;
mutable std::mutex state_mutex;
};
+[[nodiscard]] bool IsActive() noexcept;
+
+void DumpSpirvShader(u64 shader_hash, std::span<const u32> spirv_code);
+
// Helper to get stage name from index
inline const char* GetShaderStageName(size_t stage_index) {
static constexpr std::array<const char*, 5> stage_names{