Skip to content
Permalink
Browse files
Merge pull request #11522 from phire/KillRendererWithFire
Kill Renderer (with phire)
  • Loading branch information
phire committed Feb 9, 2023
2 parents 72b22ef + 5c1b3ac commit ccf92a3
Show file tree
Hide file tree
Showing 144 changed files with 5,585 additions and 4,841 deletions.
@@ -59,7 +59,7 @@
#include "UICommon/UICommon.h"

#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Present.h"
#include "VideoCommon/VideoBackendBase.h"

#include "jni/AndroidCommon/AndroidCommon.h"
@@ -456,8 +456,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang
if (s_surf == nullptr)
__android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null.");

if (g_renderer)
g_renderer->ChangeSurface(s_surf);
if (g_presenter)
g_presenter->ChangeSurface(s_surf);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*,
@@ -483,8 +483,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr

std::lock_guard surface_guard(s_surface_lock);

if (g_renderer)
g_renderer->ChangeSurface(nullptr);
if (g_presenter)
g_presenter->ChangeSurface(nullptr);

if (s_surf)
{
@@ -503,7 +503,7 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_HasSurfa
JNIEXPORT jfloat JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGameAspectRatio(JNIEnv*,
jclass)
{
return g_renderer->CalculateDrawAspectRatio();
return g_presenter->CalculateDrawAspectRatio();
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_RefreshWiimotes(JNIEnv*, jclass)
@@ -62,6 +62,7 @@ add_library(common
GekkoDisassembler.h
Hash.cpp
Hash.h
HookableEvent.h
HttpRequest.cpp
HttpRequest.h
Image.cpp
@@ -115,6 +116,7 @@ add_library(common
SocketContext.cpp
SocketContext.h
SPSCQueue.h
StringLiteral.h
StringUtil.cpp
StringUtil.h
SymbolDB.cpp
@@ -0,0 +1,102 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "Common/Logging/Log.h"
#include "Common/StringLiteral.h"

#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <string_view>
#include <vector>

namespace Common
{
struct HookBase
{
virtual ~HookBase() = default;

protected:
HookBase() = default;

// This shouldn't be copied. And since we always wrap it in unique_ptr, no need to move it either
HookBase(const HookBase&) = delete;
HookBase(HookBase&&) = delete;
HookBase& operator=(const HookBase&) = delete;
HookBase& operator=(HookBase&&) = delete;
};

// EventHook is a handle a registered listener holds.
// When the handle is destroyed, the HookableEvent will automatically remove the listener.
using EventHook = std::unique_ptr<HookBase>;

// A hookable event system.
//
// Define Events in a header as:
//
// using MyLoveyEvent = HookableEvent<"My lovely event", std::string, u32>;
//
// Register listeners anywhere you need them as:
// EventHook myHook = MyLoveyEvent::Register([](std::string foo, u32 bar) {
// fmt::print("I've been triggered with {} and {}", foo, bar)
// }, "NameOfHook");
//
// The hook will be automatically unregistered when the EventHook object goes out of scope.
// Trigger events by calling Trigger as:
//
// MyLoveyEvent::Trigger("Hello world", 42);
//
template <StringLiteral EventName, typename... CallbackArgs>
class HookableEvent
{
public:
using CallbackType = std::function<void(CallbackArgs...)>;

private:
struct HookImpl final : public HookBase
{
~HookImpl() override { HookableEvent::Remove(this); }
HookImpl(CallbackType callback, std::string name)
: m_fn(std::move(callback)), m_name(std::move(name))
{
}
CallbackType m_fn;
std::string m_name;
};

public:
// Returns a handle that will unregister the listener when destroyed.
static EventHook Register(CallbackType callback, std::string name)
{
std::lock_guard lock(m_mutex);

DEBUG_LOG_FMT(COMMON, "Registering {} handler at {} event hook", name, EventName.value);
auto handle = std::make_unique<HookImpl>(callback, std::move(name));
m_listeners.push_back(handle.get());
return handle;
}

static void Trigger(const CallbackArgs&... args)
{
std::lock_guard lock(m_mutex);

for (const auto& handle : m_listeners)
handle->m_fn(args...);
}

private:
static void Remove(HookImpl* handle)
{
std::lock_guard lock(m_mutex);

std::erase(m_listeners, handle);
}

inline static std::vector<HookImpl*> m_listeners = {};
inline static std::mutex m_mutex;
};

} // namespace Common
@@ -0,0 +1,20 @@
// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <algorithm>

namespace Common
{
// A useful template for passing string literals as arguments to templates
// from: https://ctrpeach.io/posts/cpp20-string-literal-template-parameters/
template <size_t N>
struct StringLiteral
{
consteval StringLiteral(const char (&str)[N]) { std::copy_n(str, N, value); }

char value[N];
};

} // namespace Common
@@ -84,11 +84,13 @@

#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/FrameDumper.h"
#include "VideoCommon/HiresTextures.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/PerformanceMetrics.h"
#include "VideoCommon/RenderBase.h"
#include "VideoCommon/Present.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoEvents.h"

#ifdef ANDROID
#include "jni/AndroidCommon/IDCache.h"
@@ -130,6 +132,15 @@ static thread_local bool tls_is_gpu_thread = false;

static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi);

static Common::EventHook s_frame_presented = AfterPresentEvent::Register(
[](auto& present_info) {
const double last_speed_denominator = g_perf_metrics.GetLastSpeedDenominator();
// The denominator should always be > 0 but if it's not, just return 1
const double last_speed = last_speed_denominator > 0.0 ? (1.0 / last_speed_denominator) : 1.0;
Core::Callback_FramePresented(last_speed);
},
"Core Frame Presented");

bool GetIsThrottlerTempDisabled()
{
return s_is_throttler_temp_disabled;
@@ -538,11 +549,6 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
}
Common::ScopeGuard video_guard{[] { g_video_backend->Shutdown(); }};

// Render a single frame without anything on it to clear the screen.
// This avoids the game list being displayed while the core is finishing initializing.
g_renderer->BeginUIFrame();
g_renderer->EndUIFrame();

if (cpu_info.HTT)
Config::SetBaseOrCurrent(Config::MAIN_DSP_THREAD, cpu_info.num_cores > 4);
else
@@ -731,13 +737,13 @@ static std::string GenerateScreenshotName()

void SaveScreenShot()
{
Core::RunAsCPUThread([] { g_renderer->SaveScreenshot(GenerateScreenshotName()); });
Core::RunAsCPUThread([] { g_frame_dumper->SaveScreenshot(GenerateScreenshotName()); });
}

void SaveScreenShot(std::string_view name)
{
Core::RunAsCPUThread([&name] {
g_renderer->SaveScreenshot(fmt::format("{}{}.png", GenerateScreenshotFolderPath(), name));
g_frame_dumper->SaveScreenshot(fmt::format("{}{}.png", GenerateScreenshotFolderPath(), name));
});
}

@@ -14,7 +14,12 @@
#include "Core/HW/Memmap.h"
#include "Core/System.h"

#include "VideoCommon/BPMemory.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/TextureDecoder.h"
#include "VideoCommon/VideoEvents.h"
#include "VideoCommon/XFMemory.h"
#include "VideoCommon/XFStructs.h"

class FifoRecorder::FifoRecordAnalyzer : public OpcodeDecoder::Callback
@@ -249,6 +254,42 @@ void FifoRecorder::StartRecording(s32 numFrames, CallbackFunc finishedCb)

m_RequestedRecordingEnd = false;
m_FinishedCb = finishedCb;

m_end_of_frame_event = AfterFrameEvent::Register(
[this] {
const bool was_recording = OpcodeDecoder::g_record_fifo_data;
OpcodeDecoder::g_record_fifo_data = IsRecording();

if (!OpcodeDecoder::g_record_fifo_data)
return;

if (!was_recording)
{
RecordInitialVideoMemory();
}

auto& system = Core::System::GetInstance();
auto& command_processor = system.GetCommandProcessor();
const auto& fifo = command_processor.GetFifo();
EndFrame(fifo.CPBase.load(std::memory_order_relaxed),
fifo.CPEnd.load(std::memory_order_relaxed));
},
"FifoRecorder::EndFrame");
}

void FifoRecorder::RecordInitialVideoMemory()
{
const u32* bpmem_ptr = reinterpret_cast<const u32*>(&bpmem);
u32 cpmem[256] = {};
// The FIFO recording format splits XF memory into xfmem and xfregs; follow
// that split here.
const u32* xfmem_ptr = reinterpret_cast<const u32*>(&xfmem);
const u32* xfregs_ptr = reinterpret_cast<const u32*>(&xfmem) + FifoDataFile::XF_MEM_SIZE;
u32 xfregs_size = sizeof(XFMemory) / 4 - FifoDataFile::XF_MEM_SIZE;

g_main_cp_state.FillCPMemoryArray(cpmem);

SetVideoMemory(bpmem_ptr, cpmem, xfmem_ptr, xfregs_ptr, xfregs_size, texMem);
}

void FifoRecorder::StopRecording()
@@ -391,11 +432,14 @@ void FifoRecorder::EndFrame(u32 fifoStart, u32 fifoEnd)
m_SkipFutureData = true;
// Signal video backend that it should not call this function when the next frame ends
m_IsRecording = false;

// Remove our frame end callback
m_end_of_frame_event.reset();
}
}

void FifoRecorder::SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32* xfMem,
const u32* xfRegs, u32 xfRegsSize, const u8* texMem)
const u32* xfRegs, u32 xfRegsSize, const u8* texMem_ptr)
{
std::lock_guard lk(m_mutex);

@@ -408,7 +452,7 @@ void FifoRecorder::SetVideoMemory(const u32* bpMem, const u32* cpMem, const u32*
u32 xfRegsCopySize = std::min((u32)FifoDataFile::XF_REGS_SIZE, xfRegsSize);
memcpy(m_File->GetXFRegs(), xfRegs, xfRegsCopySize * 4);

memcpy(m_File->GetTexMem(), texMem, FifoDataFile::TEX_MEM_SIZE);
memcpy(m_File->GetTexMem(), texMem_ptr, FifoDataFile::TEX_MEM_SIZE);
}

m_record_analyzer = std::make_unique<FifoRecordAnalyzer>(this, cpMem);
@@ -9,6 +9,7 @@
#include <vector>

#include "Common/Assert.h"
#include "Common/HookableEvent.h"
#include "Core/FifoPlayer/FifoDataFile.h"

class FifoRecorder
@@ -50,6 +51,8 @@ class FifoRecorder
private:
class FifoRecordAnalyzer;

void RecordInitialVideoMemory();

// Accessed from both GUI and video threads

std::recursive_mutex m_mutex;
@@ -72,4 +75,6 @@ class FifoRecorder
std::vector<u8> m_FifoData;
std::vector<u8> m_Ram;
std::vector<u8> m_ExRam;

Common::EventHook m_end_of_frame_event;
};
@@ -42,7 +42,7 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

#include "VideoCommon/FrameDump.h"
#include "VideoCommon/FrameDumpFFMpeg.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoBackendBase.h"

@@ -96,7 +96,7 @@ static size_t s_state_writes_in_queue;
static std::condition_variable s_state_write_queue_is_empty;

// Don't forget to increase this after doing changes on the savestate system
constexpr u32 STATE_VERSION = 157; // Last changed in PR 11183
constexpr u32 STATE_VERSION = 158; // Last changed in PR 11522

// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,

0 comments on commit ccf92a3

Please sign in to comment.