Files
Yaya48 c230971f07 IOS LLE: checkpoint NAND conformance and diagnostic tooling
Preserve formatted NAND boot and Wii Remote pairing, add DMA/SRAM conformance tests and a Wii comparison probe. Keep P1 profiling tools and native update A/B evidence; reject the unhelpful targeted SRAM shortcut.
2026-09-23 13:30:17 +02:00

127 lines
2.8 KiB
C++

// Copyright 2026 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <cstddef>
#include "Common/CommonTypes.h"
namespace Common::PerformanceTrace
{
// Opt-in diagnostic events, never guest state. Windows provider:
// Dolphin.Performance / {54ee9231-28be-4ab0-981e-b26f979c56a4}, schema 1.
// Set DOLPHIN_PERF_TRACE=1 before process creation and start ETW before launching.
enum class Region : u32
{
Slice,
ARM,
Jit,
Compile,
Devices,
NAND,
Journal,
JournalBuild,
JournalWrite,
JournalFlush,
NAT,
DMARead,
DMAWrite,
AES,
SHA,
Count
};
enum class Counter : u32
{
JournalTransactions,
JournalBytes,
JournalErrors,
NatRXFrames,
NatRXBytes,
NatTXFrames,
NatTXBytes,
NatPollErrors,
UsbRXFrames,
UsbRXBytes,
UsbDrops,
UsbDeliveredBytes,
NANDReads,
NANDPrograms,
NANDErases,
Count
};
struct Timing
{
u64 calls = 0;
u64 inclusive = 0;
u64 exclusive = 0;
};
// Clock-independent accounting, also exercised with deterministic timestamps in tests.
class ScopeStack
{
public:
bool Begin(Region region, u64 now);
bool End(u64 now);
void Reset();
size_t Depth() const { return m_depth; }
u64 Errors() const { return m_errors; }
const auto& Timings() const { return m_timings; }
private:
struct Entry
{
Region region;
u64 start;
u64 children;
};
std::array<Entry, 32> m_stack{};
std::array<Timing, static_cast<size_t>(Region::Count)> m_timings{};
size_t m_depth = 0;
u64 m_errors = 0;
};
bool Requested();
bool Enabled();
u64 Now();
u64 Frequency();
u64 NewGeneration();
void Add(Counter counter, u64 value = 1);
void Snapshot(u64 core_id, u64 instructions, u64 native_instructions, u64 slow_reads,
u64 slow_writes, u64 compiles, u64 fallbacks, u32 pc, bool waiting);
void CodeMap(const char* domain, const void* owner, const void* begin, const void* end,
u32 guest_pc, u64 identity, const char* kind);
void CodeReset(const char* domain, const void* owner, const void* begin, const void* end);
void Frame(const char* kind, s64 guest_ticks = 0, u32 guest_frequency = 0);
void Marker(const char* name);
void Queue(const void* owner, u64 frames, u64 bytes, u64 oldest_qpc, u64 peak);
// Only scopes inside a randomly selected root slice read the clock. No per-access timers.
class SampleRoot
{
public:
explicit SampleRoot(bool force_for_test = false);
~SampleRoot();
SampleRoot(const SampleRoot&) = delete;
SampleRoot& operator=(const SampleRoot&) = delete;
private:
bool m_active = false;
u64 m_start = 0;
u32 m_denominator = 1024;
};
class Scope
{
public:
explicit Scope(Region region);
~Scope();
Scope(const Scope&) = delete;
Scope& operator=(const Scope&) = delete;
private:
bool m_active = false;
};
} // namespace Common::PerformanceTrace