diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/gpu.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 18 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.h | 9 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.h | 10 | ||||
| -rw-r--r-- | src/video_core/gpu_thread.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/gpu_thread.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_base.h | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 69 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.h | 2 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 28 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 11 |
16 files changed, 129 insertions, 97 deletions
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index e8f763ce9..8acf2eda2 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| 9 | #include "core/core_timing_util.h" | 9 | #include "core/core_timing_util.h" |
| 10 | #include "core/frontend/emu_window.h" | ||
| 10 | #include "core/memory.h" | 11 | #include "core/memory.h" |
| 11 | #include "video_core/engines/fermi_2d.h" | 12 | #include "video_core/engines/fermi_2d.h" |
| 12 | #include "video_core/engines/kepler_compute.h" | 13 | #include "video_core/engines/kepler_compute.h" |
| @@ -16,14 +17,15 @@ | |||
| 16 | #include "video_core/gpu.h" | 17 | #include "video_core/gpu.h" |
| 17 | #include "video_core/memory_manager.h" | 18 | #include "video_core/memory_manager.h" |
| 18 | #include "video_core/renderer_base.h" | 19 | #include "video_core/renderer_base.h" |
| 20 | #include "video_core/video_core.h" | ||
| 19 | 21 | ||
| 20 | namespace Tegra { | 22 | namespace Tegra { |
| 21 | 23 | ||
| 22 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); | 24 | MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); |
| 23 | 25 | ||
| 24 | GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async) | 26 | GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, bool is_async) |
| 25 | : system{system}, renderer{renderer}, is_async{is_async} { | 27 | : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { |
| 26 | auto& rasterizer{renderer.Rasterizer()}; | 28 | auto& rasterizer{renderer->Rasterizer()}; |
| 27 | memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); | 29 | memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); |
| 28 | dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); | 30 | dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); |
| 29 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); | 31 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); |
| @@ -137,7 +139,7 @@ u64 GPU::GetTicks() const { | |||
| 137 | } | 139 | } |
| 138 | 140 | ||
| 139 | void GPU::FlushCommands() { | 141 | void GPU::FlushCommands() { |
| 140 | renderer.Rasterizer().FlushCommands(); | 142 | renderer->Rasterizer().FlushCommands(); |
| 141 | } | 143 | } |
| 142 | 144 | ||
| 143 | // Note that, traditionally, methods are treated as 4-byte addressable locations, and hence | 145 | // Note that, traditionally, methods are treated as 4-byte addressable locations, and hence |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 64acb17df..ced9d7e28 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -25,8 +25,11 @@ inline u8* FromCacheAddr(CacheAddr cache_addr) { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | namespace Core { | 27 | namespace Core { |
| 28 | class System; | 28 | namespace Frontend { |
| 29 | class EmuWindow; | ||
| 29 | } | 30 | } |
| 31 | class System; | ||
| 32 | } // namespace Core | ||
| 30 | 33 | ||
| 31 | namespace VideoCore { | 34 | namespace VideoCore { |
| 32 | class RendererBase; | 35 | class RendererBase; |
| @@ -129,7 +132,8 @@ class MemoryManager; | |||
| 129 | 132 | ||
| 130 | class GPU { | 133 | class GPU { |
| 131 | public: | 134 | public: |
| 132 | explicit GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async); | 135 | explicit GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, |
| 136 | bool is_async); | ||
| 133 | 137 | ||
| 134 | virtual ~GPU(); | 138 | virtual ~GPU(); |
| 135 | 139 | ||
| @@ -174,6 +178,14 @@ public: | |||
| 174 | /// Returns a reference to the GPU DMA pusher. | 178 | /// Returns a reference to the GPU DMA pusher. |
| 175 | Tegra::DmaPusher& DmaPusher(); | 179 | Tegra::DmaPusher& DmaPusher(); |
| 176 | 180 | ||
| 181 | VideoCore::RendererBase& Renderer() { | ||
| 182 | return *renderer; | ||
| 183 | } | ||
| 184 | |||
| 185 | const VideoCore::RendererBase& Renderer() const { | ||
| 186 | return *renderer; | ||
| 187 | } | ||
| 188 | |||
| 177 | // Waits for the GPU to finish working | 189 | // Waits for the GPU to finish working |
| 178 | virtual void WaitIdle() const = 0; | 190 | virtual void WaitIdle() const = 0; |
| 179 | 191 | ||
| @@ -287,7 +299,7 @@ private: | |||
| 287 | protected: | 299 | protected: |
| 288 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | 300 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; |
| 289 | Core::System& system; | 301 | Core::System& system; |
| 290 | VideoCore::RendererBase& renderer; | 302 | std::unique_ptr<VideoCore::RendererBase> renderer; |
| 291 | 303 | ||
| 292 | private: | 304 | private: |
| 293 | std::unique_ptr<Tegra::MemoryManager> memory_manager; | 305 | std::unique_ptr<Tegra::MemoryManager> memory_manager; |
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp index 04222d060..925be8d7b 100644 --- a/src/video_core/gpu_asynch.cpp +++ b/src/video_core/gpu_asynch.cpp | |||
| @@ -10,13 +10,16 @@ | |||
| 10 | 10 | ||
| 11 | namespace VideoCommon { | 11 | namespace VideoCommon { |
| 12 | 12 | ||
| 13 | GPUAsynch::GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer) | 13 | GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, |
| 14 | : GPU(system, renderer, true), gpu_thread{system} {} | 14 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) |
| 15 | : GPU(system, std::move(renderer_), true), gpu_thread{system}, gpu_context(std::move(context)), | ||
| 16 | cpu_context(renderer->GetRenderWindow().CreateSharedContext()) {} | ||
| 15 | 17 | ||
| 16 | GPUAsynch::~GPUAsynch() = default; | 18 | GPUAsynch::~GPUAsynch() = default; |
| 17 | 19 | ||
| 18 | void GPUAsynch::Start() { | 20 | void GPUAsynch::Start() { |
| 19 | gpu_thread.StartThread(renderer, *dma_pusher); | 21 | cpu_context->MakeCurrent(); |
| 22 | gpu_thread.StartThread(*renderer, *gpu_context, *dma_pusher); | ||
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { | 25 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { |
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h index 1241ade1d..265c62758 100644 --- a/src/video_core/gpu_asynch.h +++ b/src/video_core/gpu_asynch.h | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include "video_core/gpu.h" | 7 | #include "video_core/gpu.h" |
| 8 | #include "video_core/gpu_thread.h" | 8 | #include "video_core/gpu_thread.h" |
| 9 | 9 | ||
| 10 | namespace Core::Frontend { | ||
| 11 | class GraphicsContext; | ||
| 12 | } | ||
| 13 | |||
| 10 | namespace VideoCore { | 14 | namespace VideoCore { |
| 11 | class RendererBase; | 15 | class RendererBase; |
| 12 | } // namespace VideoCore | 16 | } // namespace VideoCore |
| @@ -16,7 +20,8 @@ namespace VideoCommon { | |||
| 16 | /// Implementation of GPU interface that runs the GPU asynchronously | 20 | /// Implementation of GPU interface that runs the GPU asynchronously |
| 17 | class GPUAsynch final : public Tegra::GPU { | 21 | class GPUAsynch final : public Tegra::GPU { |
| 18 | public: | 22 | public: |
| 19 | explicit GPUAsynch(Core::System& system, VideoCore::RendererBase& renderer); | 23 | explicit GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, |
| 24 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 20 | ~GPUAsynch() override; | 25 | ~GPUAsynch() override; |
| 21 | 26 | ||
| 22 | void Start() override; | 27 | void Start() override; |
| @@ -32,6 +37,8 @@ protected: | |||
| 32 | 37 | ||
| 33 | private: | 38 | private: |
| 34 | GPUThread::ThreadManager gpu_thread; | 39 | GPUThread::ThreadManager gpu_thread; |
| 40 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | ||
| 41 | std::unique_ptr<Core::Frontend::GraphicsContext> gpu_context; | ||
| 35 | }; | 42 | }; |
| 36 | 43 | ||
| 37 | } // namespace VideoCommon | 44 | } // namespace VideoCommon |
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp index d48221077..bd5278a5c 100644 --- a/src/video_core/gpu_synch.cpp +++ b/src/video_core/gpu_synch.cpp | |||
| @@ -7,12 +7,15 @@ | |||
| 7 | 7 | ||
| 8 | namespace VideoCommon { | 8 | namespace VideoCommon { |
| 9 | 9 | ||
| 10 | GPUSynch::GPUSynch(Core::System& system, VideoCore::RendererBase& renderer) | 10 | GPUSynch::GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, |
| 11 | : GPU(system, renderer, false) {} | 11 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context) |
| 12 | : GPU(system, std::move(renderer), false), context{std::move(context)} {} | ||
| 12 | 13 | ||
| 13 | GPUSynch::~GPUSynch() = default; | 14 | GPUSynch::~GPUSynch() = default; |
| 14 | 15 | ||
| 15 | void GPUSynch::Start() {} | 16 | void GPUSynch::Start() { |
| 17 | context->MakeCurrent(); | ||
| 18 | } | ||
| 16 | 19 | ||
| 17 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | 20 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
| 18 | dma_pusher->Push(std::move(entries)); | 21 | dma_pusher->Push(std::move(entries)); |
| @@ -20,19 +23,19 @@ void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | |||
| 20 | } | 23 | } |
| 21 | 24 | ||
| 22 | void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | 25 | void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
| 23 | renderer.SwapBuffers(framebuffer); | 26 | renderer->SwapBuffers(framebuffer); |
| 24 | } | 27 | } |
| 25 | 28 | ||
| 26 | void GPUSynch::FlushRegion(CacheAddr addr, u64 size) { | 29 | void GPUSynch::FlushRegion(CacheAddr addr, u64 size) { |
| 27 | renderer.Rasterizer().FlushRegion(addr, size); | 30 | renderer->Rasterizer().FlushRegion(addr, size); |
| 28 | } | 31 | } |
| 29 | 32 | ||
| 30 | void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) { | 33 | void GPUSynch::InvalidateRegion(CacheAddr addr, u64 size) { |
| 31 | renderer.Rasterizer().InvalidateRegion(addr, size); | 34 | renderer->Rasterizer().InvalidateRegion(addr, size); |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { | 37 | void GPUSynch::FlushAndInvalidateRegion(CacheAddr addr, u64 size) { |
| 35 | renderer.Rasterizer().FlushAndInvalidateRegion(addr, size); | 38 | renderer->Rasterizer().FlushAndInvalidateRegion(addr, size); |
| 36 | } | 39 | } |
| 37 | 40 | ||
| 38 | } // namespace VideoCommon | 41 | } // namespace VideoCommon |
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h index c71baee89..866a94c8c 100644 --- a/src/video_core/gpu_synch.h +++ b/src/video_core/gpu_synch.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | #include "video_core/gpu.h" | 7 | #include "video_core/gpu.h" |
| 8 | 8 | ||
| 9 | namespace Core::Frontend { | ||
| 10 | class GraphicsContext; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace VideoCore { | 13 | namespace VideoCore { |
| 10 | class RendererBase; | 14 | class RendererBase; |
| 11 | } // namespace VideoCore | 15 | } // namespace VideoCore |
| @@ -15,7 +19,8 @@ namespace VideoCommon { | |||
| 15 | /// Implementation of GPU interface that runs the GPU synchronously | 19 | /// Implementation of GPU interface that runs the GPU synchronously |
| 16 | class GPUSynch final : public Tegra::GPU { | 20 | class GPUSynch final : public Tegra::GPU { |
| 17 | public: | 21 | public: |
| 18 | explicit GPUSynch(Core::System& system, VideoCore::RendererBase& renderer); | 22 | explicit GPUSynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer, |
| 23 | std::unique_ptr<Core::Frontend::GraphicsContext>&& context); | ||
| 19 | ~GPUSynch() override; | 24 | ~GPUSynch() override; |
| 20 | 25 | ||
| 21 | void Start() override; | 26 | void Start() override; |
| @@ -29,6 +34,9 @@ public: | |||
| 29 | protected: | 34 | protected: |
| 30 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, | 35 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, |
| 31 | [[maybe_unused]] u32 value) const override {} | 36 | [[maybe_unused]] u32 value) const override {} |
| 37 | |||
| 38 | private: | ||
| 39 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||
| 32 | }; | 40 | }; |
| 33 | 41 | ||
| 34 | } // namespace VideoCommon | 42 | } // namespace VideoCommon |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index b1088af3d..270c7ae0d 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/microprofile.h" | 6 | #include "common/microprofile.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/frontend/scope_acquire_context.h" | 8 | #include "core/frontend/emu_window.h" |
| 9 | #include "video_core/dma_pusher.h" | 9 | #include "video_core/dma_pusher.h" |
| 10 | #include "video_core/gpu.h" | 10 | #include "video_core/gpu.h" |
| 11 | #include "video_core/gpu_thread.h" | 11 | #include "video_core/gpu_thread.h" |
| @@ -14,8 +14,8 @@ | |||
| 14 | namespace VideoCommon::GPUThread { | 14 | namespace VideoCommon::GPUThread { |
| 15 | 15 | ||
| 16 | /// Runs the GPU thread | 16 | /// Runs the GPU thread |
| 17 | static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher, | 17 | static void RunThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, |
| 18 | SynchState& state) { | 18 | Tegra::DmaPusher& dma_pusher, SynchState& state) { |
| 19 | MicroProfileOnThreadCreate("GpuThread"); | 19 | MicroProfileOnThreadCreate("GpuThread"); |
| 20 | 20 | ||
| 21 | // Wait for first GPU command before acquiring the window context | 21 | // Wait for first GPU command before acquiring the window context |
| @@ -27,7 +27,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p | |||
| 27 | return; | 27 | return; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | Core::Frontend::ScopeAcquireContext acquire_context{renderer.GetRenderWindow()}; | 30 | auto current_context = context.Acquire(); |
| 31 | 31 | ||
| 32 | CommandDataContainer next; | 32 | CommandDataContainer next; |
| 33 | while (state.is_running) { | 33 | while (state.is_running) { |
| @@ -62,8 +62,11 @@ ThreadManager::~ThreadManager() { | |||
| 62 | thread.join(); | 62 | thread.join(); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher) { | 65 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, |
| 66 | thread = std::thread{RunThread, std::ref(renderer), std::ref(dma_pusher), std::ref(state)}; | 66 | Core::Frontend::GraphicsContext& context, |
| 67 | Tegra::DmaPusher& dma_pusher) { | ||
| 68 | thread = std::thread{RunThread, std::ref(renderer), std::ref(context), std::ref(dma_pusher), | ||
| 69 | std::ref(state)}; | ||
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { | 72 | void ThreadManager::SubmitList(Tegra::CommandList&& entries) { |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 882e2d9c7..be36c580e 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include <optional> | 10 | #include <optional> |
| 11 | #include <thread> | 11 | #include <thread> |
| 12 | #include <variant> | 12 | #include <variant> |
| 13 | |||
| 14 | #include "common/threadsafe_queue.h" | 13 | #include "common/threadsafe_queue.h" |
| 15 | #include "video_core/gpu.h" | 14 | #include "video_core/gpu.h" |
| 16 | 15 | ||
| @@ -20,6 +19,9 @@ class DmaPusher; | |||
| 20 | } // namespace Tegra | 19 | } // namespace Tegra |
| 21 | 20 | ||
| 22 | namespace Core { | 21 | namespace Core { |
| 22 | namespace Frontend { | ||
| 23 | class GraphicsContext; | ||
| 24 | } | ||
| 23 | class System; | 25 | class System; |
| 24 | } // namespace Core | 26 | } // namespace Core |
| 25 | 27 | ||
| @@ -99,7 +101,8 @@ public: | |||
| 99 | ~ThreadManager(); | 101 | ~ThreadManager(); |
| 100 | 102 | ||
| 101 | /// Creates and starts the GPU thread. | 103 | /// Creates and starts the GPU thread. |
| 102 | void StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_pusher); | 104 | void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context, |
| 105 | Tegra::DmaPusher& dma_pusher); | ||
| 103 | 106 | ||
| 104 | /// Push GPU command entries to be processed | 107 | /// Push GPU command entries to be processed |
| 105 | void SubmitList(Tegra::CommandList&& entries); | 108 | void SubmitList(Tegra::CommandList&& entries); |
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 5ec99a126..1d85219b6 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -46,7 +46,8 @@ public: | |||
| 46 | 46 | ||
| 47 | /// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer | 47 | /// Draws the latest frame to the window waiting timeout_ms for a frame to arrive (Renderer |
| 48 | /// specific implementation) | 48 | /// specific implementation) |
| 49 | virtual void TryPresent(int timeout_ms) = 0; | 49 | /// Returns true if a frame was drawn |
| 50 | virtual bool TryPresent(int timeout_ms) = 0; | ||
| 50 | 51 | ||
| 51 | // Getter/setter functions: | 52 | // Getter/setter functions: |
| 52 | // ------------------------ | 53 | // ------------------------ |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index e3d31c3eb..8f59e0442 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -305,7 +305,6 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, | |||
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | const std::vector gl_cache = disk_cache.LoadPrecompiled(); | 307 | const std::vector gl_cache = disk_cache.LoadPrecompiled(); |
| 308 | const auto supported_formats = GetSupportedFormats(); | ||
| 309 | 308 | ||
| 310 | // Track if precompiled cache was altered during loading to know if we have to | 309 | // Track if precompiled cache was altered during loading to know if we have to |
| 311 | // serialize the virtual precompiled cache file back to the hard drive | 310 | // serialize the virtual precompiled cache file back to the hard drive |
| @@ -327,8 +326,8 @@ void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, | |||
| 327 | 326 | ||
| 328 | const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin, | 327 | const auto worker = [&](Core::Frontend::GraphicsContext* context, std::size_t begin, |
| 329 | std::size_t end) { | 328 | std::size_t end) { |
| 330 | context->MakeCurrent(); | 329 | const auto scope = context->Acquire(); |
| 331 | SCOPE_EXIT({ return context->DoneCurrent(); }); | 330 | const auto supported_formats = GetSupportedFormats(); |
| 332 | 331 | ||
| 333 | for (std::size_t i = begin; i < end; ++i) { | 332 | for (std::size_t i = begin; i < end; ++i) { |
| 334 | if (stop_loading) { | 333 | if (stop_loading) { |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index fca5e3ec0..6f08803c1 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -7,9 +7,7 @@ | |||
| 7 | #include <cstdlib> | 7 | #include <cstdlib> |
| 8 | #include <cstring> | 8 | #include <cstring> |
| 9 | #include <memory> | 9 | #include <memory> |
| 10 | |||
| 11 | #include <glad/glad.h> | 10 | #include <glad/glad.h> |
| 12 | |||
| 13 | #include "common/assert.h" | 11 | #include "common/assert.h" |
| 14 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 15 | #include "common/microprofile.h" | 13 | #include "common/microprofile.h" |
| @@ -30,8 +28,6 @@ namespace OpenGL { | |||
| 30 | 28 | ||
| 31 | namespace { | 29 | namespace { |
| 32 | 30 | ||
| 33 | // If the size of this is too small, it ends up creating a soft cap on FPS as the renderer will have | ||
| 34 | // to wait on available presentation frames. | ||
| 35 | constexpr std::size_t SWAP_CHAIN_SIZE = 3; | 31 | constexpr std::size_t SWAP_CHAIN_SIZE = 3; |
| 36 | 32 | ||
| 37 | struct Frame { | 33 | struct Frame { |
| @@ -214,7 +210,7 @@ public: | |||
| 214 | std::deque<Frame*> present_queue; | 210 | std::deque<Frame*> present_queue; |
| 215 | Frame* previous_frame{}; | 211 | Frame* previous_frame{}; |
| 216 | 212 | ||
| 217 | FrameMailbox() : has_debug_tool{HasDebugTool()} { | 213 | FrameMailbox() { |
| 218 | for (auto& frame : swap_chain) { | 214 | for (auto& frame : swap_chain) { |
| 219 | free_queue.push(&frame); | 215 | free_queue.push(&frame); |
| 220 | } | 216 | } |
| @@ -285,13 +281,9 @@ public: | |||
| 285 | std::unique_lock lock{swap_chain_lock}; | 281 | std::unique_lock lock{swap_chain_lock}; |
| 286 | present_queue.push_front(frame); | 282 | present_queue.push_front(frame); |
| 287 | present_cv.notify_one(); | 283 | present_cv.notify_one(); |
| 288 | |||
| 289 | DebugNotifyNextFrame(); | ||
| 290 | } | 284 | } |
| 291 | 285 | ||
| 292 | Frame* TryGetPresentFrame(int timeout_ms) { | 286 | Frame* TryGetPresentFrame(int timeout_ms) { |
| 293 | DebugWaitForNextFrame(); | ||
| 294 | |||
| 295 | std::unique_lock lock{swap_chain_lock}; | 287 | std::unique_lock lock{swap_chain_lock}; |
| 296 | // wait for new entries in the present_queue | 288 | // wait for new entries in the present_queue |
| 297 | present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), | 289 | present_cv.wait_for(lock, std::chrono::milliseconds(timeout_ms), |
| @@ -317,38 +309,12 @@ public: | |||
| 317 | previous_frame = frame; | 309 | previous_frame = frame; |
| 318 | return frame; | 310 | return frame; |
| 319 | } | 311 | } |
| 320 | |||
| 321 | private: | ||
| 322 | std::mutex debug_synch_mutex; | ||
| 323 | std::condition_variable debug_synch_condition; | ||
| 324 | std::atomic_int frame_for_debug{}; | ||
| 325 | const bool has_debug_tool; // When true, using a GPU debugger, so keep frames in lock-step | ||
| 326 | |||
| 327 | /// Signal that a new frame is available (called from GPU thread) | ||
| 328 | void DebugNotifyNextFrame() { | ||
| 329 | if (!has_debug_tool) { | ||
| 330 | return; | ||
| 331 | } | ||
| 332 | frame_for_debug++; | ||
| 333 | std::lock_guard lock{debug_synch_mutex}; | ||
| 334 | debug_synch_condition.notify_one(); | ||
| 335 | } | ||
| 336 | |||
| 337 | /// Wait for a new frame to be available (called from presentation thread) | ||
| 338 | void DebugWaitForNextFrame() { | ||
| 339 | if (!has_debug_tool) { | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | const int last_frame = frame_for_debug; | ||
| 343 | std::unique_lock lock{debug_synch_mutex}; | ||
| 344 | debug_synch_condition.wait(lock, | ||
| 345 | [this, last_frame] { return frame_for_debug > last_frame; }); | ||
| 346 | } | ||
| 347 | }; | 312 | }; |
| 348 | 313 | ||
| 349 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system) | 314 | RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, |
| 350 | : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, | 315 | Core::Frontend::GraphicsContext& context) |
| 351 | frame_mailbox{std::make_unique<FrameMailbox>()} {} | 316 | : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, frame_mailbox{}, |
| 317 | has_debug_tool{HasDebugTool()}, context{context} {} | ||
| 352 | 318 | ||
| 353 | RendererOpenGL::~RendererOpenGL() = default; | 319 | RendererOpenGL::~RendererOpenGL() = default; |
| 354 | 320 | ||
| @@ -356,8 +322,6 @@ MICROPROFILE_DEFINE(OpenGL_RenderFrame, "OpenGL", "Render Frame", MP_RGB(128, 12 | |||
| 356 | MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128)); | 322 | MICROPROFILE_DEFINE(OpenGL_WaitPresent, "OpenGL", "Wait For Present", MP_RGB(128, 128, 128)); |
| 357 | 323 | ||
| 358 | void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | 324 | void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
| 359 | render_window.PollEvents(); | ||
| 360 | |||
| 361 | if (!framebuffer) { | 325 | if (!framebuffer) { |
| 362 | return; | 326 | return; |
| 363 | } | 327 | } |
| @@ -413,6 +377,13 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 413 | m_current_frame++; | 377 | m_current_frame++; |
| 414 | rasterizer->TickFrame(); | 378 | rasterizer->TickFrame(); |
| 415 | } | 379 | } |
| 380 | |||
| 381 | render_window.PollEvents(); | ||
| 382 | if (has_debug_tool) { | ||
| 383 | glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); | ||
| 384 | Present(0); | ||
| 385 | context.SwapBuffers(); | ||
| 386 | } | ||
| 416 | } | 387 | } |
| 417 | 388 | ||
| 418 | void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { | 389 | void RendererOpenGL::PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer) { |
| @@ -480,6 +451,8 @@ void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color | |||
| 480 | } | 451 | } |
| 481 | 452 | ||
| 482 | void RendererOpenGL::InitOpenGLObjects() { | 453 | void RendererOpenGL::InitOpenGLObjects() { |
| 454 | frame_mailbox = std::make_unique<FrameMailbox>(); | ||
| 455 | |||
| 483 | glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, | 456 | glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue, |
| 484 | 0.0f); | 457 | 0.0f); |
| 485 | 458 | ||
| @@ -692,12 +665,21 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 692 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 665 | glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 693 | } | 666 | } |
| 694 | 667 | ||
| 695 | void RendererOpenGL::TryPresent(int timeout_ms) { | 668 | bool RendererOpenGL::TryPresent(int timeout_ms) { |
| 669 | if (has_debug_tool) { | ||
| 670 | LOG_DEBUG(Render_OpenGL, | ||
| 671 | "Skipping presentation because we are presenting on the main context"); | ||
| 672 | return false; | ||
| 673 | } | ||
| 674 | return Present(timeout_ms); | ||
| 675 | } | ||
| 676 | |||
| 677 | bool RendererOpenGL::Present(int timeout_ms) { | ||
| 696 | const auto& layout = render_window.GetFramebufferLayout(); | 678 | const auto& layout = render_window.GetFramebufferLayout(); |
| 697 | auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms); | 679 | auto frame = frame_mailbox->TryGetPresentFrame(timeout_ms); |
| 698 | if (!frame) { | 680 | if (!frame) { |
| 699 | LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present"); | 681 | LOG_DEBUG(Render_OpenGL, "TryGetPresentFrame returned no frame to present"); |
| 700 | return; | 682 | return false; |
| 701 | } | 683 | } |
| 702 | 684 | ||
| 703 | // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a | 685 | // Clearing before a full overwrite of a fbo can signal to drivers that they can avoid a |
| @@ -725,6 +707,7 @@ void RendererOpenGL::TryPresent(int timeout_ms) { | |||
| 725 | glFlush(); | 707 | glFlush(); |
| 726 | 708 | ||
| 727 | glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); | 709 | glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); |
| 710 | return true; | ||
| 728 | } | 711 | } |
| 729 | 712 | ||
| 730 | void RendererOpenGL::RenderScreenshot() { | 713 | void RendererOpenGL::RenderScreenshot() { |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 33073ce5b..50b647661 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -55,13 +55,14 @@ class FrameMailbox; | |||
| 55 | 55 | ||
| 56 | class RendererOpenGL final : public VideoCore::RendererBase { | 56 | class RendererOpenGL final : public VideoCore::RendererBase { |
| 57 | public: | 57 | public: |
| 58 | explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system); | 58 | explicit RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, |
| 59 | Core::Frontend::GraphicsContext& context); | ||
| 59 | ~RendererOpenGL() override; | 60 | ~RendererOpenGL() override; |
| 60 | 61 | ||
| 61 | bool Init() override; | 62 | bool Init() override; |
| 62 | void ShutDown() override; | 63 | void ShutDown() override; |
| 63 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | 64 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; |
| 64 | void TryPresent(int timeout_ms) override; | 65 | bool TryPresent(int timeout_ms) override; |
| 65 | 66 | ||
| 66 | private: | 67 | private: |
| 67 | /// Initializes the OpenGL state and creates persistent objects. | 68 | /// Initializes the OpenGL state and creates persistent objects. |
| @@ -89,8 +90,11 @@ private: | |||
| 89 | 90 | ||
| 90 | void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); | 91 | void PrepareRendertarget(const Tegra::FramebufferConfig* framebuffer); |
| 91 | 92 | ||
| 93 | bool Present(int timeout_ms); | ||
| 94 | |||
| 92 | Core::Frontend::EmuWindow& emu_window; | 95 | Core::Frontend::EmuWindow& emu_window; |
| 93 | Core::System& system; | 96 | Core::System& system; |
| 97 | Core::Frontend::GraphicsContext& context; | ||
| 94 | 98 | ||
| 95 | StateTracker state_tracker{system}; | 99 | StateTracker state_tracker{system}; |
| 96 | 100 | ||
| @@ -115,6 +119,8 @@ private: | |||
| 115 | 119 | ||
| 116 | /// Frame presentation mailbox | 120 | /// Frame presentation mailbox |
| 117 | std::unique_ptr<FrameMailbox> frame_mailbox; | 121 | std::unique_ptr<FrameMailbox> frame_mailbox; |
| 122 | |||
| 123 | bool has_debug_tool = false; | ||
| 118 | }; | 124 | }; |
| 119 | 125 | ||
| 120 | } // namespace OpenGL | 126 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 42bb01418..6953aaafe 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -141,8 +141,9 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 141 | render_window.PollEvents(); | 141 | render_window.PollEvents(); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | void RendererVulkan::TryPresent(int /*timeout_ms*/) { | 144 | bool RendererVulkan::TryPresent(int /*timeout_ms*/) { |
| 145 | // TODO (bunnei): ImplementMe | 145 | // TODO (bunnei): ImplementMe |
| 146 | return true; | ||
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | bool RendererVulkan::Init() { | 149 | bool RendererVulkan::Init() { |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 3da08d2e4..d14384e79 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -42,7 +42,7 @@ public: | |||
| 42 | bool Init() override; | 42 | bool Init() override; |
| 43 | void ShutDown() override; | 43 | void ShutDown() override; |
| 44 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | 44 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; |
| 45 | void TryPresent(int timeout_ms) override; | 45 | bool TryPresent(int timeout_ms) override; |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
| 48 | std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( | 48 | std::optional<vk::DebugUtilsMessengerEXT> CreateDebugCallback( |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index a5f81a8a0..fd9fec018 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -15,13 +15,13 @@ | |||
| 15 | #endif | 15 | #endif |
| 16 | #include "video_core/video_core.h" | 16 | #include "video_core/video_core.h" |
| 17 | 17 | ||
| 18 | namespace VideoCore { | 18 | namespace { |
| 19 | 19 | std::unique_ptr<VideoCore::RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | |
| 20 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | 20 | Core::System& system, |
| 21 | Core::System& system) { | 21 | Core::Frontend::GraphicsContext& context) { |
| 22 | switch (Settings::values.renderer_backend) { | 22 | switch (Settings::values.renderer_backend) { |
| 23 | case Settings::RendererBackend::OpenGL: | 23 | case Settings::RendererBackend::OpenGL: |
| 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system); | 24 | return std::make_unique<OpenGL::RendererOpenGL>(emu_window, system, context); |
| 25 | #ifdef HAS_VULKAN | 25 | #ifdef HAS_VULKAN |
| 26 | case Settings::RendererBackend::Vulkan: | 26 | case Settings::RendererBackend::Vulkan: |
| 27 | return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); | 27 | return std::make_unique<Vulkan::RendererVulkan>(emu_window, system); |
| @@ -30,13 +30,23 @@ std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_wind | |||
| 30 | return nullptr; | 30 | return nullptr; |
| 31 | } | 31 | } |
| 32 | } | 32 | } |
| 33 | } // namespace | ||
| 33 | 34 | ||
| 34 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) { | 35 | namespace VideoCore { |
| 35 | if (Settings::values.use_asynchronous_gpu_emulation) { | 36 | |
| 36 | return std::make_unique<VideoCommon::GPUAsynch>(system, system.Renderer()); | 37 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { |
| 38 | auto context = emu_window.CreateSharedContext(); | ||
| 39 | const auto scope = context->Acquire(); | ||
| 40 | auto renderer = CreateRenderer(emu_window, system, *context); | ||
| 41 | if (!renderer->Init()) { | ||
| 42 | return {}; | ||
| 37 | } | 43 | } |
| 38 | 44 | ||
| 39 | return std::make_unique<VideoCommon::GPUSynch>(system, system.Renderer()); | 45 | if (Settings::values.use_asynchronous_gpu_emulation) { |
| 46 | return std::make_unique<VideoCommon::GPUAsynch>(system, std::move(renderer), | ||
| 47 | std::move(context)); | ||
| 48 | } | ||
| 49 | return std::make_unique<VideoCommon::GPUSynch>(system, std::move(renderer), std::move(context)); | ||
| 40 | } | 50 | } |
| 41 | 51 | ||
| 42 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 52 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index b8e0ac372..f5c27125d 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h | |||
| @@ -22,17 +22,8 @@ namespace VideoCore { | |||
| 22 | 22 | ||
| 23 | class RendererBase; | 23 | class RendererBase; |
| 24 | 24 | ||
| 25 | /** | ||
| 26 | * Creates a renderer instance. | ||
| 27 | * | ||
| 28 | * @note The returned renderer instance is simply allocated. Its Init() | ||
| 29 | * function still needs to be called to fully complete its setup. | ||
| 30 | */ | ||
| 31 | std::unique_ptr<RendererBase> CreateRenderer(Core::Frontend::EmuWindow& emu_window, | ||
| 32 | Core::System& system); | ||
| 33 | |||
| 34 | /// Creates an emulated GPU instance using the given system context. | 25 | /// Creates an emulated GPU instance using the given system context. |
| 35 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system); | 26 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system); |
| 36 | 27 | ||
| 37 | u16 GetResolutionScaleFactor(const RendererBase& renderer); | 28 | u16 GetResolutionScaleFactor(const RendererBase& renderer); |
| 38 | 29 | ||