mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-20 06:47:53 -05:00
Merge pull request #3552 from jroweboy/single-context
Refactor Context management (Fixes renderdoc on opengl issues)
This commit is contained in:
@ -7,6 +7,7 @@
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "core/memory.h"
|
||||
#include "video_core/engines/fermi_2d.h"
|
||||
#include "video_core/engines/kepler_compute.h"
|
||||
@ -16,14 +17,15 @@
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/memory_manager.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace Tegra {
|
||||
|
||||
MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
|
||||
|
||||
GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async)
|
||||
: system{system}, renderer{renderer}, is_async{is_async} {
|
||||
auto& rasterizer{renderer.Rasterizer()};
|
||||
GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async)
|
||||
: system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
|
||||
auto& rasterizer{renderer->Rasterizer()};
|
||||
memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
|
||||
dma_pusher = std::make_unique<Tegra::DmaPusher>(*this);
|
||||
maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
|
||||
@ -137,7 +139,7 @@ u64 GPU::GetTicks() const {
|
||||
}
|
||||
|
||||
void GPU::FlushCommands() {
|
||||
renderer.Rasterizer().FlushCommands();
|
||||
renderer->Rasterizer().FlushCommands();
|
||||
}
|
||||
|
||||
// Note that, traditionally, methods are treated as 4-byte addressable locations, and hence
|
||||
|
@ -25,8 +25,11 @@ inline u8* FromCacheAddr(CacheAddr cache_addr) {
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
namespace Frontend {
|
||||
class EmuWindow;
|
||||
}
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
@ -129,7 +132,8 @@ class MemoryManager;
|
||||
|
||||
class GPU {
|
||||
public:
|
||||
explicit GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async);
|
||||
explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
bool is_async);
|
||||
|
||||
virtual ~GPU();
|
||||
|
||||
@ -174,6 +178,14 @@ public:
|
||||
/// Returns a reference to the GPU DMA pusher.
|
||||
Tegra::DmaPusher& DmaPusher();
|
||||
|
||||
VideoCore::RendererBase& Renderer() {
|
||||
return *renderer;
|
||||
}
|
||||
|
||||
const VideoCore::RendererBase& Renderer() const {
|
||||
return *renderer;
|
||||
}
|
||||
|
||||
// Waits for the GPU to finish working
|
||||
virtual void WaitIdle() const = 0;
|
||||
|
||||
@ -287,7 +299,7 @@ private:
|
||||
protected:
|
||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
||||
Core::System& system;
|
||||
VideoCore::RendererBase& renderer;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Tegra::MemoryManager> memory_manager;
|
||||
|
@ -10,13 +10,16 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer)
|
||||
: GPU(system, renderer, true), gpu_thread{system} {}
|
||||
GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer_), true), gpu_thread{system}, gpu_context(std::move(context)),
|
||||
cpu_context(renderer->GetRenderWindow().CreateSharedContext()) {}
|
||||
|
||||
GPUAsynch::~GPUAsynch() = default;
|
||||
|
||||
void GPUAsynch::Start() {
|
||||
gpu_thread.StartThread(renderer, *dma_pusher);
|
||||
cpu_context->MakeCurrent();
|
||||
gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher);
|
||||
}
|
||||
|
||||
void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
|
@ -7,6 +7,10 @@
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/gpu_thread.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
} // namespace VideoCore
|
||||
@ -16,7 +20,8 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU asynchronously
|
||||
class GPUAsynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer);
|
||||
explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
~GPUAsynch() override;
|
||||
|
||||
void Start() override;
|
||||
@ -32,6 +37,8 @@ protected:
|
||||
|
||||
private:
|
||||
GPUThread::ThreadManager gpu_thread;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
@ -7,12 +7,15 @@
|
||||
|
||||
namespace VideoCommon {
|
||||
|
||||
GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer)
|
||||
: GPU(system, renderer, false) {}
|
||||
GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
|
||||
: GPU(system, std::move(renderer), false), context{std::move(context)} {}
|
||||
|
||||
GPUSynch::~GPUSynch() = default;
|
||||
|
||||
void GPUSynch::Start() {}
|
||||
void GPUSynch::Start() {
|
||||
context->MakeCurrent();
|
||||
}
|
||||
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
dma_pusher->Push(std::move(entries));
|
||||
@ -20,19 +23,19 @@ void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
|
||||
}
|
||||
|
||||
void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
renderer.SwapBuffers(framebuffer);
|
||||
renderer->SwapBuffers(framebuffer);
|
||||
}
|
||||
|
||||
void GPUSynch::FlushRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().FlushRegion(addr, size);
|
||||
renderer->Rasterizer().FlushRegion(addr, size);
|
||||
}
|
||||
|
||||
void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().InvalidateRegion(addr, size);
|
||||
renderer->Rasterizer().InvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) {
|
||||
renderer.Rasterizer().FlushAndInvalidateRegion(addr, size);
|
||||
renderer->Rasterizer().FlushAndInvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
@ -6,6 +6,10 @@
|
||||
|
||||
#include "video_core/gpu.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
|
||||
namespace VideoCore {
|
||||
class RendererBase;
|
||||
} // namespace VideoCore
|
||||
@ -15,7 +19,8 @@ namespace VideoCommon {
|
||||
/// Implementation of GPU interface that runs the GPU synchronously
|
||||
class GPUSynch final : public Tegra::GPU {
|
||||
public:
|
||||
explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer);
|
||||
explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer,
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext>&& context);
|
||||
~GPUSynch() override;
|
||||
|
||||
void Start() override;
|
||||
@ -29,6 +34,9 @@ public:
|
||||
protected:
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id,
|
||||
[[maybe_unused]] u32 value) const override {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> context;
|
||||
};
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "core/core.h"
|
||||
#include "core/frontend/scope_acquire_context.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
#include "video_core/dma_pusher.h"
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/gpu_thread.h"
|
||||
@ -14,8 +14,8 @@
|
||||
namespace VideoCommon::GPUThread {
|
||||
|
||||
/// Runs the GPU thread
|
||||
static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher,
|
||||
SynchState& state) {
|
||||
static void RunThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher, SynchState& state) {
|
||||
MicroProfileOnThreadCreate("GpuThread");
|
||||
|
||||
// Wait for first GPU command before acquiring the window context
|
||||
@ -27,7 +27,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p
|
||||
return;
|
||||
}
|
||||
|
||||
Core::Frontend::ScopeAcquireContext acquire_context{renderer.GetRenderWindow()};
|
||||
auto current_context = context.Acquire();
|
||||
|
||||
CommandDataContainer next;
|
||||
while (state.is_running) {
|
||||
@ -62,8 +62,11 @@ ThreadManager::~ThreadManager() {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) {
|
||||
thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)};
|
||||
void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
|
||||
Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher) {
|
||||
thread = std::thread{RunThread, std::ref(renderer), std::ref(context), std::ref(dma_pusher),
|
||||
std::ref(state)};
|
||||
}
|
||||
|
||||
void ThreadManager::SubmitList(Tegra::CommandList&& entries) {
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <variant>
|
||||
|
||||
#include "common/threadsafe_queue.h"
|
||||
#include "video_core/gpu.h"
|
||||
|
||||
@ -20,6 +19,9 @@ class DmaPusher;
|
||||
} // namespace Tegra
|
||||
|
||||
namespace Core {
|
||||
namespace Frontend {
|
||||
class GraphicsContext;
|
||||
}
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
@ -99,7 +101,8 @@ public:
|
||||
~ThreadManager();
|
||||
|
||||
/// Creates and starts the GPU thread.
|
||||
void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher);
|
||||
void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
|
||||
Tegra::DmaPusher& dma_pusher);
|
||||
|
||||
/// Push GPU command entries to be processed
|
||||
void SubmitList(Tegra::CommandList&& entries);
|
||||
|
@ -46,7 +46,8 @@ public:
|
||||
|
||||
/// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer
|
||||
/// specific implementation)
|
||||
virtual void TryPresent(int timeout_ms) = 0;
|
||||
/// Returns true if a frame was drawn
|
||||
virtual bool TryPresent(int timeout_ms) = 0;
|
||||
|
||||
// Getter/setter functions:
|
||||
// ------------------------
|
||||
|
@ -327,8 +327,7 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
|
||||
|
||||
const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin,
|
||||
std::size_t end) {
|
||||
context->MakeCurrent();
|
||||
SCOPE_EXIT({ return context->DoneCurrent(); });
|
||||
const auto scope = context->Acquire();
|
||||
|
||||
for (std::size_t i = begin; i < end; ++i) {
|
||||
if (stop_loading) {
|
||||
|
@ -30,8 +30,6 @@ namespace OpenGL {
|
||||
|
||||
namespace {
|
||||
|
||||
// If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have
|
||||
// to wait on available presentation frames.
|
||||
constexpr std::size_t SWAP_CHAIN_SIZE = 3;
|
||||
|
||||
struct Frame {
|
||||
@ -214,7 +212,7 @@ public:
|
||||
std::deque<Frame*> present_queue;
|
||||
Frame* previous_frame{};
|
||||
|
||||
FrameMailbox() : has_debug_tool{HasDebugTool()} {
|
||||
FrameMailbox() {
|
||||
for (auto& frame : swap_chain) {
|
||||
free_queue.push(&frame);
|
||||
}
|
||||
@ -285,13 +283,9 @@ public:
|
||||
std::unique_lock lock{swap_chain_lock};
|
||||
present_queue.push_front(frame);
|
||||
present_cv.notify_one();
|
||||
|
||||
DebugNotifyNextFrame();
|
||||
}
|
||||
|
||||
Frame* TryGetPresentFrame(int timeout_ms) {
|
||||
DebugWaitForNextFrame();
|
||||
|
||||
std::unique_lock lock{swap_chain_lock};
|
||||
// wait for new entries in the present_queue
|
||||
present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms),
|
||||
@ -317,38 +311,12 @@ public:
|
||||
previous_frame = frame;
|
||||
return frame;
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex debug_synch_mutex;
|
||||
std::condition_variable debug_synch_condition;
|
||||
std::atomic_int frame_for_debug{};
|
||||
const bool has_debug_tool; // When true, using a GPU debugger, so keep frames in lock-step
|
||||
|
||||
/// Signal that a new frame is available (called from GPU thread)
|
||||
void DebugNotifyNextFrame() {
|
||||
if (!has_debug_tool) {
|
||||
return;
|
||||
}
|
||||
frame_for_debug++;
|
||||
std::lock_guard lock{debug_synch_mutex};
|
||||
debug_synch_condition.notify_one();
|
||||
}
|
||||
|
||||
/// Wait for a new frame to be available (called from presentation thread)
|
||||
void DebugWaitForNextFrame() {
|
||||
if (!has_debug_tool) {
|
||||
return;
|
||||
}
|
||||
const int last_frame = frame_for_debug;
|
||||
std::unique_lock lock{debug_synch_mutex};
|
||||
debug_synch_condition.wait(lock,
|
||||
[this, last_frame] { return frame_for_debug > last_frame; });
|
||||
}
|
||||
};
|
||||
|
||||
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system)
|
||||
RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context)
|
||||
: VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system},
|
||||
frame_mailbox{std::make_unique<FrameMailbox>()} {}
|
||||
frame_mailbox{}, context{context}, has_debug_tool{HasDebugTool()} {}
|
||||
|
||||
RendererOpenGL::~RendererOpenGL() = default;
|
||||
|
||||
@ -356,8 +324,6 @@ MICROPROFILE_DEFINE(OpenGL_RenderFrame, "OpenGL", "Render Frame", MP_RGB(128, 12
|
||||
MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128));
|
||||
|
||||
void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
render_window.PollEvents();
|
||||
|
||||
if (!framebuffer) {
|
||||
return;
|
||||
}
|
||||
@ -413,6 +379,13 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
m_current_frame++;
|
||||
rasterizer->TickFrame();
|
||||
}
|
||||
|
||||
render_window.PollEvents();
|
||||
if (has_debug_tool) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
Present(0);
|
||||
context.SwapBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) {
|
||||
@ -480,6 +453,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color
|
||||
}
|
||||
|
||||
void RendererOpenGL::InitOpenGLObjects() {
|
||||
frame_mailbox = std::make_unique<FrameMailbox>();
|
||||
|
||||
glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
|
||||
0.0f);
|
||||
|
||||
@ -692,12 +667,21 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
void RendererOpenGL::TryPresent(int timeout_ms) {
|
||||
bool RendererOpenGL::TryPresent(int timeout_ms) {
|
||||
if (has_debug_tool) {
|
||||
LOG_DEBUG(Render_OpenGL,
|
||||
"Skipping presentation because we are presenting on the main context");
|
||||
return false;
|
||||
}
|
||||
return Present(timeout_ms);
|
||||
}
|
||||
|
||||
bool RendererOpenGL::Present(int timeout_ms) {
|
||||
const auto& layout = render_window.GetFramebufferLayout();
|
||||
auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms);
|
||||
if (!frame) {
|
||||
LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a
|
||||
@ -725,6 +709,7 @@ void RendererOpenGL::TryPresent(int timeout_ms) {
|
||||
glFlush();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RendererOpenGL::RenderScreenshot() {
|
||||
|
@ -55,13 +55,14 @@ class FrameMailbox;
|
||||
|
||||
class RendererOpenGL final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system);
|
||||
explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context);
|
||||
~RendererOpenGL() override;
|
||||
|
||||
bool Init() override;
|
||||
void ShutDown() override;
|
||||
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
||||
void TryPresent(int timeout_ms) override;
|
||||
bool TryPresent(int timeout_ms) override;
|
||||
|
||||
private:
|
||||
/// Initializes the OpenGL state and creates persistent objects.
|
||||
@ -89,8 +90,11 @@ private:
|
||||
|
||||
void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer);
|
||||
|
||||
bool Present(int timeout_ms);
|
||||
|
||||
Core::Frontend::EmuWindow& emu_window;
|
||||
Core::System& system;
|
||||
Core::Frontend::GraphicsContext& context;
|
||||
|
||||
StateTracker state_tracker{system};
|
||||
|
||||
@ -115,6 +119,8 @@ private:
|
||||
|
||||
/// Frame presentation mailbox
|
||||
std::unique_ptr<FrameMailbox> frame_mailbox;
|
||||
|
||||
bool has_debug_tool = false;
|
||||
};
|
||||
|
||||
} // namespace OpenGL
|
||||
|
@ -141,8 +141,9 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||
render_window.PollEvents();
|
||||
}
|
||||
|
||||
void RendererVulkan::TryPresent(int /*timeout_ms*/) {
|
||||
bool RendererVulkan::TryPresent(int /*timeout_ms*/) {
|
||||
// TODO (bunnei): ImplementMe
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RendererVulkan::Init() {
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
bool Init() override;
|
||||
void ShutDown() override;
|
||||
void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override;
|
||||
void TryPresent(int timeout_ms) override;
|
||||
bool TryPresent(int timeout_ms) override;
|
||||
|
||||
private:
|
||||
std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback(
|
||||
|
@ -15,13 +15,13 @@
|
||||
#endif
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system) {
|
||||
namespace {
|
||||
std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system,
|
||||
Core::Frontend::GraphicsContext& context) {
|
||||
switch (Settings::values.renderer_backend) {
|
||||
case Settings::RendererBackend::OpenGL:
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system);
|
||||
return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context);
|
||||
#ifdef HAS_VULKAN
|
||||
case Settings::RendererBackend::Vulkan:
|
||||
return std::make_unique<Vulkan::RendererVulkan>(emu_window, system);
|
||||
@ -30,13 +30,23 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) {
|
||||
if (Settings::values.use_asynchronous_gpu_emulation) {
|
||||
return std::make_unique<VideoCommon::GPUAsynch>(system, system.Renderer());
|
||||
namespace VideoCore {
|
||||
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) {
|
||||
auto context = emu_window.CreateSharedContext();
|
||||
const auto scope = context->Acquire();
|
||||
auto renderer = CreateRenderer(emu_window, system, *context);
|
||||
if (!renderer->Init()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<VideoCommon::GPUSynch>(system, system.Renderer());
|
||||
if (Settings::values.use_asynchronous_gpu_emulation) {
|
||||
return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer),
|
||||
std::move(context));
|
||||
}
|
||||
return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context));
|
||||
}
|
||||
|
||||
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
|
||||
|
@ -22,17 +22,8 @@ namespace VideoCore {
|
||||
|
||||
class RendererBase;
|
||||
|
||||
/**
|
||||
* Creates a renderer instance.
|
||||
*
|
||||
* @note The returned renderer instance is simply allocated. Its Init()
|
||||
* function still needs to be called to fully complete its setup.
|
||||
*/
|
||||
std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window,
|
||||
Core::System& system);
|
||||
|
||||
/// Creates an emulated GPU instance using the given system context.
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system);
|
||||
std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system);
|
||||
|
||||
u16 GetResolutionScaleFactor(const RendererBase& renderer);
|
||||
|
||||
|
Reference in New Issue
Block a user