gpu: Refactor a/synchronous implementations into their own classes.

This commit is contained in:
bunnei 2019-02-08 23:21:53 -05:00
parent 7b574f406b
commit aaa373585c
8 changed files with 162 additions and 65 deletions

View file

@ -36,7 +36,8 @@
#include "frontend/applets/software_keyboard.h" #include "frontend/applets/software_keyboard.h"
#include "frontend/applets/web_browser.h" #include "frontend/applets/web_browser.h"
#include "video_core/debug_utils/debug_utils.h" #include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu.h" #include "video_core/gpu_asynch.h"
#include "video_core/gpu_synch.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
#include "video_core/video_core.h" #include "video_core/video_core.h"
@ -131,7 +132,11 @@ struct System::Impl {
is_powered_on = true; is_powered_on = true;
gpu_core = std::make_unique<Tegra::GPU>(system, *renderer); if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer);
} else {
gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer);
}
cpu_core_manager.Initialize(system); cpu_core_manager.Initialize(system);

View file

@ -17,6 +17,10 @@ add_library(video_core STATIC
engines/shader_header.h engines/shader_header.h
gpu.cpp gpu.cpp
gpu.h gpu.h
gpu_asynch.cpp
gpu_asynch.h
gpu_synch.cpp
gpu_synch.h
gpu_thread.cpp gpu_thread.cpp
gpu_thread.h gpu_thread.h
macro_interpreter.cpp macro_interpreter.cpp

View file

@ -6,14 +6,12 @@
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/memory.h" #include "core/memory.h"
#include "core/settings.h"
#include "video_core/engines/fermi_2d.h" #include "video_core/engines/fermi_2d.h"
#include "video_core/engines/kepler_compute.h" #include "video_core/engines/kepler_compute.h"
#include "video_core/engines/kepler_memory.h" #include "video_core/engines/kepler_memory.h"
#include "video_core/engines/maxwell_3d.h" #include "video_core/engines/maxwell_3d.h"
#include "video_core/engines/maxwell_dma.h" #include "video_core/engines/maxwell_dma.h"
#include "video_core/gpu.h" #include "video_core/gpu.h"
#include "video_core/gpu_thread.h"
#include "video_core/renderer_base.h" #include "video_core/renderer_base.h"
namespace Tegra { namespace Tegra {
@ -39,10 +37,6 @@ GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer) : renderer{ren
kepler_compute = std::make_unique<Engines::KeplerCompute>(*memory_manager); kepler_compute = std::make_unique<Engines::KeplerCompute>(*memory_manager);
maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, rasterizer, *memory_manager); maxwell_dma = std::make_unique<Engines::MaxwellDMA>(system, rasterizer, *memory_manager);
kepler_memory = std::make_unique<Engines::KeplerMemory>(system, rasterizer, *memory_manager); kepler_memory = std::make_unique<Engines::KeplerMemory>(system, rasterizer, *memory_manager);
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread = std::make_unique<VideoCommon::GPUThread::ThreadManager>(renderer, *dma_pusher);
}
} }
GPU::~GPU() = default; GPU::~GPU() = default;
@ -71,48 +65,6 @@ const DmaPusher& GPU::DmaPusher() const {
return *dma_pusher; return *dma_pusher;
} }
void GPU::PushGPUEntries(Tegra::CommandList&& entries) {
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread->SubmitList(std::move(entries));
} else {
dma_pusher->Push(std::move(entries));
dma_pusher->DispatchCalls();
}
}
void GPU::SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) {
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread->SwapBuffers(std::move(framebuffer));
} else {
renderer.SwapBuffers(std::move(framebuffer));
}
}
void GPU::FlushRegion(VAddr addr, u64 size) {
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread->FlushRegion(addr, size);
} else {
renderer.Rasterizer().FlushRegion(addr, size);
}
}
void GPU::InvalidateRegion(VAddr addr, u64 size) {
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread->InvalidateRegion(addr, size);
} else {
renderer.Rasterizer().InvalidateRegion(addr, size);
}
}
void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) {
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_thread->FlushAndInvalidateRegion(addr, size);
} else {
renderer.Rasterizer().FlushAndInvalidateRegion(addr, size);
}
}
u32 RenderTargetBytesPerPixel(RenderTargetFormat format) { u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
ASSERT(format != RenderTargetFormat::NONE); ASSERT(format != RenderTargetFormat::NONE);

View file

@ -19,10 +19,6 @@ namespace VideoCore {
class RendererBase; class RendererBase;
} // namespace VideoCore } // namespace VideoCore
namespace VideoCommon::GPUThread {
class ThreadManager;
} // namespace VideoCommon::GPUThread
namespace Tegra { namespace Tegra {
enum class RenderTargetFormat : u32 { enum class RenderTargetFormat : u32 {
@ -123,7 +119,7 @@ enum class EngineID {
MAXWELL_DMA_COPY_A = 0xB0B5, MAXWELL_DMA_COPY_A = 0xB0B5,
}; };
class GPU final { class GPU {
public: public:
explicit GPU(Core::System& system, VideoCore::RendererBase& renderer); explicit GPU(Core::System& system, VideoCore::RendererBase& renderer);
@ -206,20 +202,20 @@ public:
} regs{}; } regs{};
/// Push GPU command entries to be processed /// Push GPU command entries to be processed
void PushGPUEntries(Tegra::CommandList&& entries); virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0;
/// Swap buffers (render frame) /// Swap buffers (render frame)
void SwapBuffers( virtual void SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer); std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) = 0;
/// Notify rasterizer that any caches of the specified region should be flushed to Switch memory /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
void FlushRegion(VAddr addr, u64 size); virtual void FlushRegion(VAddr addr, u64 size) = 0;
/// Notify rasterizer that any caches of the specified region should be invalidated /// Notify rasterizer that any caches of the specified region should be invalidated
void InvalidateRegion(VAddr addr, u64 size); virtual void InvalidateRegion(VAddr addr, u64 size) = 0;
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
void FlushAndInvalidateRegion(VAddr addr, u64 size); virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0;
private: private:
void ProcessBindMethod(const MethodCall& method_call); void ProcessBindMethod(const MethodCall& method_call);
@ -236,13 +232,13 @@ private:
/// Determines where the method should be executed. /// Determines where the method should be executed.
bool ExecuteMethodOnEngine(const MethodCall& method_call); bool ExecuteMethodOnEngine(const MethodCall& method_call);
private: protected:
std::unique_ptr<Tegra::DmaPusher> dma_pusher; std::unique_ptr<Tegra::DmaPusher> dma_pusher;
std::unique_ptr<Tegra::MemoryManager> memory_manager;
std::unique_ptr<VideoCommon::GPUThread::ThreadManager> gpu_thread;
VideoCore::RendererBase& renderer; VideoCore::RendererBase& renderer;
private:
std::unique_ptr<Tegra::MemoryManager> memory_manager;
/// Mapping of command subchannels to their bound engine ids. /// Mapping of command subchannels to their bound engine ids.
std::array<EngineID, 8> bound_engines = {}; std::array<EngineID, 8> bound_engines = {};

View file

@ -0,0 +1,37 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "video_core/gpu_asynch.h"
#include "video_core/gpu_thread.h"
#include "video_core/renderer_base.h"
namespace VideoCommon {
GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer)
: Tegra::GPU(system, renderer), gpu_thread{renderer, *dma_pusher} {}
GPUAsynch::~GPUAsynch() = default;
void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) {
gpu_thread.SubmitList(std::move(entries));
}
void GPUAsynch::SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) {
gpu_thread.SwapBuffers(std::move(framebuffer));
}
void GPUAsynch::FlushRegion(VAddr addr, u64 size) {
gpu_thread.FlushRegion(addr, size);
}
void GPUAsynch::InvalidateRegion(VAddr addr, u64 size) {
gpu_thread.InvalidateRegion(addr, size);
}
void GPUAsynch::FlushAndInvalidateRegion(VAddr addr, u64 size) {
gpu_thread.FlushAndInvalidateRegion(addr, size);
}
} // namespace VideoCommon

View file

@ -0,0 +1,37 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "video_core/gpu.h"
#include "video_core/gpu_thread.h"
namespace VideoCore {
class RendererBase;
} // namespace VideoCore
namespace VideoCommon {
namespace GPUThread {
class ThreadManager;
} // namespace GPUThread
/// Implementation of GPU interface that runs the GPU asynchronously
class GPUAsynch : public Tegra::GPU {
public:
explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer);
~GPUAsynch();
void PushGPUEntries(Tegra::CommandList&& entries) override;
void SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override;
void FlushRegion(VAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
private:
GPUThread::ThreadManager gpu_thread;
};
} // namespace VideoCommon

View file

@ -0,0 +1,37 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "video_core/gpu_synch.h"
#include "video_core/renderer_base.h"
namespace VideoCommon {
GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer)
: Tegra::GPU(system, renderer) {}
GPUSynch::~GPUSynch() = default;
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) {
dma_pusher->Push(std::move(entries));
dma_pusher->DispatchCalls();
}
void GPUSynch::SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) {
renderer.SwapBuffers(std::move(framebuffer));
}
void GPUSynch::FlushRegion(VAddr addr, u64 size) {
renderer.Rasterizer().FlushRegion(addr, size);
}
void GPUSynch::InvalidateRegion(VAddr addr, u64 size) {
renderer.Rasterizer().InvalidateRegion(addr, size);
}
void GPUSynch::FlushAndInvalidateRegion(VAddr addr, u64 size) {
renderer.Rasterizer().FlushAndInvalidateRegion(addr, size);
}
} // namespace VideoCommon

View file

@ -0,0 +1,29 @@
// Copyright 2019 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "video_core/gpu.h"
namespace VideoCore {
class RendererBase;
} // namespace VideoCore
namespace VideoCommon {
/// Implementation of GPU interface that runs the GPU synchronously
class GPUSynch : public Tegra::GPU {
public:
explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer);
~GPUSynch();
void PushGPUEntries(Tegra::CommandList&& entries) override;
void SwapBuffers(
std::optional<std::reference_wrapper<const Tegra::FramebufferConfig>> framebuffer) override;
void FlushRegion(VAddr addr, u64 size) override;
void InvalidateRegion(VAddr addr, u64 size) override;
void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
};
} // namespace VideoCommon