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.
127 lines
2.8 KiB
C++
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
|