diff options
| -rw-r--r-- | src/video_core/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | src/video_core/framebuffer_config.h | 31 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 76 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 55 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.cpp | 86 | ||||
| -rw-r--r-- | src/video_core/gpu_asynch.h | 47 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.cpp | 61 | ||||
| -rw-r--r-- | src/video_core/gpu_synch.h | 41 | ||||
| -rw-r--r-- | src/video_core/gpu_thread.h | 7 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 10 |
10 files changed, 130 insertions, 289 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 5b73724ce..4111ce8f7 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -47,6 +47,7 @@ add_library(video_core STATIC | |||
| 47 | engines/shader_bytecode.h | 47 | engines/shader_bytecode.h |
| 48 | engines/shader_header.h | 48 | engines/shader_header.h |
| 49 | engines/shader_type.h | 49 | engines/shader_type.h |
| 50 | framebuffer_config.h | ||
| 50 | macro/macro.cpp | 51 | macro/macro.cpp |
| 51 | macro/macro.h | 52 | macro/macro.h |
| 52 | macro/macro_hle.cpp | 53 | macro/macro_hle.cpp |
| @@ -58,10 +59,6 @@ add_library(video_core STATIC | |||
| 58 | fence_manager.h | 59 | fence_manager.h |
| 59 | gpu.cpp | 60 | gpu.cpp |
| 60 | gpu.h | 61 | gpu.h |
| 61 | gpu_asynch.cpp | ||
| 62 | gpu_asynch.h | ||
| 63 | gpu_synch.cpp | ||
| 64 | gpu_synch.h | ||
| 65 | gpu_thread.cpp | 62 | gpu_thread.cpp |
| 66 | gpu_thread.h | 63 | gpu_thread.h |
| 67 | guest_driver.cpp | 64 | guest_driver.cpp |
diff --git a/src/video_core/framebuffer_config.h b/src/video_core/framebuffer_config.h new file mode 100644 index 000000000..b86c3a757 --- /dev/null +++ b/src/video_core/framebuffer_config.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | namespace Tegra { | ||
| 8 | |||
| 9 | /** | ||
| 10 | * Struct describing framebuffer configuration | ||
| 11 | */ | ||
| 12 | struct FramebufferConfig { | ||
| 13 | enum class PixelFormat : u32 { | ||
| 14 | A8B8G8R8_UNORM = 1, | ||
| 15 | RGB565_UNORM = 4, | ||
| 16 | B8G8R8A8_UNORM = 5, | ||
| 17 | }; | ||
| 18 | |||
| 19 | VAddr address{}; | ||
| 20 | u32 offset{}; | ||
| 21 | u32 width{}; | ||
| 22 | u32 height{}; | ||
| 23 | u32 stride{}; | ||
| 24 | PixelFormat pixel_format{}; | ||
| 25 | |||
| 26 | using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; | ||
| 27 | TransformFlags transform_flags{}; | ||
| 28 | Common::Rectangle<int> crop_rect; | ||
| 29 | }; | ||
| 30 | |||
| 31 | } // namespace Tegra | ||
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index e2512a7f2..f99a8a0de 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "core/core_timing.h" | 10 | #include "core/core_timing.h" |
| 11 | #include "core/core_timing_util.h" | 11 | #include "core/core_timing_util.h" |
| 12 | #include "core/frontend/emu_window.h" | 12 | #include "core/frontend/emu_window.h" |
| 13 | #include "core/hardware_interrupt_manager.h" | ||
| 13 | #include "core/memory.h" | 14 | #include "core/memory.h" |
| 14 | #include "core/settings.h" | 15 | #include "core/settings.h" |
| 15 | #include "video_core/engines/fermi_2d.h" | 16 | #include "video_core/engines/fermi_2d.h" |
| @@ -36,7 +37,8 @@ GPU::GPU(Core::System& system_, bool is_async_, bool use_nvdec_) | |||
| 36 | kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)}, | 37 | kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)}, |
| 37 | maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, | 38 | maxwell_dma{std::make_unique<Engines::MaxwellDMA>(system, *memory_manager)}, |
| 38 | kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, | 39 | kepler_memory{std::make_unique<Engines::KeplerMemory>(system, *memory_manager)}, |
| 39 | shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_} {} | 40 | shader_notify{std::make_unique<VideoCore::ShaderNotify>()}, is_async{is_async_}, |
| 41 | gpu_thread{system_} {} | ||
| 40 | 42 | ||
| 41 | GPU::~GPU() = default; | 43 | GPU::~GPU() = default; |
| 42 | 44 | ||
| @@ -198,10 +200,6 @@ void GPU::SyncGuestHost() { | |||
| 198 | renderer->Rasterizer().SyncGuestHost(); | 200 | renderer->Rasterizer().SyncGuestHost(); |
| 199 | } | 201 | } |
| 200 | 202 | ||
| 201 | void GPU::OnCommandListEnd() { | ||
| 202 | renderer->Rasterizer().ReleaseFences(); | ||
| 203 | } | ||
| 204 | |||
| 205 | enum class GpuSemaphoreOperation { | 203 | enum class GpuSemaphoreOperation { |
| 206 | AcquireEqual = 0x1, | 204 | AcquireEqual = 0x1, |
| 207 | WriteLong = 0x2, | 205 | WriteLong = 0x2, |
| @@ -461,4 +459,72 @@ void GPU::ProcessSemaphoreAcquire() { | |||
| 461 | } | 459 | } |
| 462 | } | 460 | } |
| 463 | 461 | ||
| 462 | void GPU::Start() { | ||
| 463 | gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher, *cdma_pusher); | ||
| 464 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 465 | cpu_context->MakeCurrent(); | ||
| 466 | } | ||
| 467 | |||
| 468 | void GPU::ObtainContext() { | ||
| 469 | cpu_context->MakeCurrent(); | ||
| 470 | } | ||
| 471 | |||
| 472 | void GPU::ReleaseContext() { | ||
| 473 | cpu_context->DoneCurrent(); | ||
| 474 | } | ||
| 475 | |||
| 476 | void GPU::PushGPUEntries(Tegra::CommandList&& entries) { | ||
| 477 | gpu_thread.SubmitList(std::move(entries)); | ||
| 478 | } | ||
| 479 | |||
| 480 | void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { | ||
| 481 | if (!use_nvdec) { | ||
| 482 | return; | ||
| 483 | } | ||
| 484 | // This condition fires when a video stream ends, clear all intermediary data | ||
| 485 | if (entries[0].raw == 0xDEADB33F) { | ||
| 486 | cdma_pusher.reset(); | ||
| 487 | return; | ||
| 488 | } | ||
| 489 | if (!cdma_pusher) { | ||
| 490 | cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this); | ||
| 491 | } | ||
| 492 | |||
| 493 | // SubmitCommandBuffer would make the nvdec operations async, this is not currently working | ||
| 494 | // TODO(ameerj): RE proper async nvdec operation | ||
| 495 | // gpu_thread.SubmitCommandBuffer(std::move(entries)); | ||
| 496 | |||
| 497 | cdma_pusher->Push(std::move(entries)); | ||
| 498 | cdma_pusher->DispatchCalls(); | ||
| 499 | } | ||
| 500 | |||
| 501 | void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||
| 502 | gpu_thread.SwapBuffers(framebuffer); | ||
| 503 | } | ||
| 504 | |||
| 505 | void GPU::FlushRegion(VAddr addr, u64 size) { | ||
| 506 | gpu_thread.FlushRegion(addr, size); | ||
| 507 | } | ||
| 508 | |||
| 509 | void GPU::InvalidateRegion(VAddr addr, u64 size) { | ||
| 510 | gpu_thread.InvalidateRegion(addr, size); | ||
| 511 | } | ||
| 512 | |||
| 513 | void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) { | ||
| 514 | gpu_thread.FlushAndInvalidateRegion(addr, size); | ||
| 515 | } | ||
| 516 | |||
| 517 | void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { | ||
| 518 | auto& interrupt_manager = system.InterruptManager(); | ||
| 519 | interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); | ||
| 520 | } | ||
| 521 | |||
| 522 | void GPU::WaitIdle() const { | ||
| 523 | gpu_thread.WaitIdle(); | ||
| 524 | } | ||
| 525 | |||
| 526 | void GPU::OnCommandListEnd() { | ||
| 527 | gpu_thread.OnCommandListEnd(); | ||
| 528 | } | ||
| 529 | |||
| 464 | } // namespace Tegra | 530 | } // namespace Tegra |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 660641d04..a2bb4d82d 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include "core/hle/service/nvflinger/buffer_queue.h" | 15 | #include "core/hle/service/nvflinger/buffer_queue.h" |
| 16 | #include "video_core/cdma_pusher.h" | 16 | #include "video_core/cdma_pusher.h" |
| 17 | #include "video_core/dma_pusher.h" | 17 | #include "video_core/dma_pusher.h" |
| 18 | #include "video_core/framebuffer_config.h" | ||
| 19 | #include "video_core/gpu_thread.h" | ||
| 18 | 20 | ||
| 19 | using CacheAddr = std::uintptr_t; | 21 | using CacheAddr = std::uintptr_t; |
| 20 | [[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) { | 22 | [[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) { |
| @@ -101,28 +103,6 @@ enum class DepthFormat : u32 { | |||
| 101 | struct CommandListHeader; | 103 | struct CommandListHeader; |
| 102 | class DebugContext; | 104 | class DebugContext; |
| 103 | 105 | ||
| 104 | /** | ||
| 105 | * Struct describing framebuffer configuration | ||
| 106 | */ | ||
| 107 | struct FramebufferConfig { | ||
| 108 | enum class PixelFormat : u32 { | ||
| 109 | A8B8G8R8_UNORM = 1, | ||
| 110 | RGB565_UNORM = 4, | ||
| 111 | B8G8R8A8_UNORM = 5, | ||
| 112 | }; | ||
| 113 | |||
| 114 | VAddr address; | ||
| 115 | u32 offset; | ||
| 116 | u32 width; | ||
| 117 | u32 height; | ||
| 118 | u32 stride; | ||
| 119 | PixelFormat pixel_format; | ||
| 120 | |||
| 121 | using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; | ||
| 122 | TransformFlags transform_flags; | ||
| 123 | Common::Rectangle<int> crop_rect; | ||
| 124 | }; | ||
| 125 | |||
| 126 | namespace Engines { | 106 | namespace Engines { |
| 127 | class Fermi2D; | 107 | class Fermi2D; |
| 128 | class Maxwell3D; | 108 | class Maxwell3D; |
| @@ -141,7 +121,7 @@ enum class EngineID { | |||
| 141 | 121 | ||
| 142 | class MemoryManager; | 122 | class MemoryManager; |
| 143 | 123 | ||
| 144 | class GPU { | 124 | class GPU final { |
| 145 | public: | 125 | public: |
| 146 | struct MethodCall { | 126 | struct MethodCall { |
| 147 | u32 method{}; | 127 | u32 method{}; |
| @@ -159,7 +139,7 @@ public: | |||
| 159 | }; | 139 | }; |
| 160 | 140 | ||
| 161 | explicit GPU(Core::System& system_, bool is_async_, bool use_nvdec_); | 141 | explicit GPU(Core::System& system_, bool is_async_, bool use_nvdec_); |
| 162 | virtual ~GPU(); | 142 | ~GPU(); |
| 163 | 143 | ||
| 164 | /// Binds a renderer to the GPU. | 144 | /// Binds a renderer to the GPU. |
| 165 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer); | 145 | void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer); |
| @@ -176,7 +156,7 @@ public: | |||
| 176 | /// Synchronizes CPU writes with Host GPU memory. | 156 | /// Synchronizes CPU writes with Host GPU memory. |
| 177 | void SyncGuestHost(); | 157 | void SyncGuestHost(); |
| 178 | /// Signal the ending of command list. | 158 | /// Signal the ending of command list. |
| 179 | virtual void OnCommandListEnd(); | 159 | void OnCommandListEnd(); |
| 180 | 160 | ||
| 181 | /// Request a host GPU memory flush from the CPU. | 161 | /// Request a host GPU memory flush from the CPU. |
| 182 | [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size); | 162 | [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size); |
| @@ -240,7 +220,7 @@ public: | |||
| 240 | } | 220 | } |
| 241 | 221 | ||
| 242 | // Waits for the GPU to finish working | 222 | // Waits for the GPU to finish working |
| 243 | virtual void WaitIdle() const = 0; | 223 | void WaitIdle() const; |
| 244 | 224 | ||
| 245 | /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. | 225 | /// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame. |
| 246 | void WaitFence(u32 syncpoint_id, u32 value); | 226 | void WaitFence(u32 syncpoint_id, u32 value); |
| @@ -330,34 +310,34 @@ public: | |||
| 330 | /// Performs any additional setup necessary in order to begin GPU emulation. | 310 | /// Performs any additional setup necessary in order to begin GPU emulation. |
| 331 | /// This can be used to launch any necessary threads and register any necessary | 311 | /// This can be used to launch any necessary threads and register any necessary |
| 332 | /// core timing events. | 312 | /// core timing events. |
| 333 | virtual void Start() = 0; | 313 | void Start(); |
| 334 | 314 | ||
| 335 | /// Obtain the CPU Context | 315 | /// Obtain the CPU Context |
| 336 | virtual void ObtainContext() = 0; | 316 | void ObtainContext(); |
| 337 | 317 | ||
| 338 | /// Release the CPU Context | 318 | /// Release the CPU Context |
| 339 | virtual void ReleaseContext() = 0; | 319 | void ReleaseContext(); |
| 340 | 320 | ||
| 341 | /// Push GPU command entries to be processed | 321 | /// Push GPU command entries to be processed |
| 342 | virtual void PushGPUEntries(Tegra::CommandList&& entries) = 0; | 322 | void PushGPUEntries(Tegra::CommandList&& entries); |
| 343 | 323 | ||
| 344 | /// Push GPU command buffer entries to be processed | 324 | /// Push GPU command buffer entries to be processed |
| 345 | virtual void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) = 0; | 325 | void PushCommandBuffer(Tegra::ChCommandHeaderList& entries); |
| 346 | 326 | ||
| 347 | /// Swap buffers (render frame) | 327 | /// Swap buffers (render frame) |
| 348 | virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0; | 328 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); |
| 349 | 329 | ||
| 350 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory | 330 | /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory |
| 351 | virtual void FlushRegion(VAddr addr, u64 size) = 0; | 331 | void FlushRegion(VAddr addr, u64 size); |
| 352 | 332 | ||
| 353 | /// Notify rasterizer that any caches of the specified region should be invalidated | 333 | /// Notify rasterizer that any caches of the specified region should be invalidated |
| 354 | virtual void InvalidateRegion(VAddr addr, u64 size) = 0; | 334 | void InvalidateRegion(VAddr addr, u64 size); |
| 355 | 335 | ||
| 356 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated | 336 | /// Notify rasterizer that any caches of the specified region should be flushed and invalidated |
| 357 | virtual void FlushAndInvalidateRegion(VAddr addr, u64 size) = 0; | 337 | void FlushAndInvalidateRegion(VAddr addr, u64 size); |
| 358 | 338 | ||
| 359 | protected: | 339 | protected: |
| 360 | virtual void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const = 0; | 340 | void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const; |
| 361 | 341 | ||
| 362 | private: | 342 | private: |
| 363 | void ProcessBindMethod(const MethodCall& method_call); | 343 | void ProcessBindMethod(const MethodCall& method_call); |
| @@ -426,6 +406,9 @@ private: | |||
| 426 | u64 last_flush_fence{}; | 406 | u64 last_flush_fence{}; |
| 427 | std::mutex flush_request_mutex; | 407 | std::mutex flush_request_mutex; |
| 428 | 408 | ||
| 409 | VideoCommon::GPUThread::ThreadManager gpu_thread; | ||
| 410 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | ||
| 411 | |||
| 429 | const bool is_async; | 412 | const bool is_async; |
| 430 | }; | 413 | }; |
| 431 | 414 | ||
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp deleted file mode 100644 index 6cc091ecd..000000000 --- a/src/video_core/gpu_asynch.cpp +++ /dev/null | |||
| @@ -1,86 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hardware_interrupt_manager.h" | ||
| 7 | #include "video_core/gpu_asynch.h" | ||
| 8 | #include "video_core/gpu_thread.h" | ||
| 9 | #include "video_core/renderer_base.h" | ||
| 10 | |||
| 11 | namespace VideoCommon { | ||
| 12 | |||
| 13 | GPUAsynch::GPUAsynch(Core::System& system_, bool use_nvdec_) | ||
| 14 | : GPU{system_, true, use_nvdec_}, gpu_thread{system_} {} | ||
| 15 | |||
| 16 | GPUAsynch::~GPUAsynch() = default; | ||
| 17 | |||
| 18 | void GPUAsynch::Start() { | ||
| 19 | gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher, *cdma_pusher); | ||
| 20 | cpu_context = renderer->GetRenderWindow().CreateSharedContext(); | ||
| 21 | cpu_context->MakeCurrent(); | ||
| 22 | } | ||
| 23 | |||
| 24 | void GPUAsynch::ObtainContext() { | ||
| 25 | cpu_context->MakeCurrent(); | ||
| 26 | } | ||
| 27 | |||
| 28 | void GPUAsynch::ReleaseContext() { | ||
| 29 | cpu_context->DoneCurrent(); | ||
| 30 | } | ||
| 31 | |||
| 32 | void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { | ||
| 33 | gpu_thread.SubmitList(std::move(entries)); | ||
| 34 | } | ||
| 35 | |||
| 36 | void GPUAsynch::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { | ||
| 37 | if (!use_nvdec) { | ||
| 38 | return; | ||
| 39 | } | ||
| 40 | // This condition fires when a video stream ends, clear all intermediary data | ||
| 41 | if (entries[0].raw == 0xDEADB33F) { | ||
| 42 | cdma_pusher.reset(); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | if (!cdma_pusher) { | ||
| 46 | cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this); | ||
| 47 | } | ||
| 48 | |||
| 49 | // SubmitCommandBuffer would make the nvdec operations async, this is not currently working | ||
| 50 | // TODO(ameerj): RE proper async nvdec operation | ||
| 51 | // gpu_thread.SubmitCommandBuffer(std::move(entries)); | ||
| 52 | |||
| 53 | cdma_pusher->Push(std::move(entries)); | ||
| 54 | cdma_pusher->DispatchCalls(); | ||
| 55 | } | ||
| 56 | |||
| 57 | void GPUAsynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||
| 58 | gpu_thread.SwapBuffers(framebuffer); | ||
| 59 | } | ||
| 60 | |||
| 61 | void GPUAsynch::FlushRegion(VAddr addr, u64 size) { | ||
| 62 | gpu_thread.FlushRegion(addr, size); | ||
| 63 | } | ||
| 64 | |||
| 65 | void GPUAsynch::InvalidateRegion(VAddr addr, u64 size) { | ||
| 66 | gpu_thread.InvalidateRegion(addr, size); | ||
| 67 | } | ||
| 68 | |||
| 69 | void GPUAsynch::FlushAndInvalidateRegion(VAddr addr, u64 size) { | ||
| 70 | gpu_thread.FlushAndInvalidateRegion(addr, size); | ||
| 71 | } | ||
| 72 | |||
| 73 | void GPUAsynch::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { | ||
| 74 | auto& interrupt_manager = system.InterruptManager(); | ||
| 75 | interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); | ||
| 76 | } | ||
| 77 | |||
| 78 | void GPUAsynch::WaitIdle() const { | ||
| 79 | gpu_thread.WaitIdle(); | ||
| 80 | } | ||
| 81 | |||
| 82 | void GPUAsynch::OnCommandListEnd() { | ||
| 83 | gpu_thread.OnCommandListEnd(); | ||
| 84 | } | ||
| 85 | |||
| 86 | } // namespace VideoCommon | ||
diff --git a/src/video_core/gpu_asynch.h b/src/video_core/gpu_asynch.h deleted file mode 100644 index a384113f4..000000000 --- a/src/video_core/gpu_asynch.h +++ /dev/null | |||
| @@ -1,47 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "video_core/gpu.h" | ||
| 8 | #include "video_core/gpu_thread.h" | ||
| 9 | |||
| 10 | namespace Core::Frontend { | ||
| 11 | class GraphicsContext; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace VideoCore { | ||
| 15 | class RendererBase; | ||
| 16 | } // namespace VideoCore | ||
| 17 | |||
| 18 | namespace VideoCommon { | ||
| 19 | |||
| 20 | /// Implementation of GPU interface that runs the GPU asynchronously | ||
| 21 | class GPUAsynch final : public Tegra::GPU { | ||
| 22 | public: | ||
| 23 | explicit GPUAsynch(Core::System& system_, bool use_nvdec_); | ||
| 24 | ~GPUAsynch() override; | ||
| 25 | |||
| 26 | void Start() override; | ||
| 27 | void ObtainContext() override; | ||
| 28 | void ReleaseContext() override; | ||
| 29 | void PushGPUEntries(Tegra::CommandList&& entries) override; | ||
| 30 | void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) override; | ||
| 31 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | ||
| 32 | void FlushRegion(VAddr addr, u64 size) override; | ||
| 33 | void InvalidateRegion(VAddr addr, u64 size) override; | ||
| 34 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||
| 35 | void WaitIdle() const override; | ||
| 36 | |||
| 37 | void OnCommandListEnd() override; | ||
| 38 | |||
| 39 | protected: | ||
| 40 | void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const override; | ||
| 41 | |||
| 42 | private: | ||
| 43 | GPUThread::ThreadManager gpu_thread; | ||
| 44 | std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; | ||
| 45 | }; | ||
| 46 | |||
| 47 | } // namespace VideoCommon | ||
diff --git a/src/video_core/gpu_synch.cpp b/src/video_core/gpu_synch.cpp deleted file mode 100644 index 1e9d4b9b2..000000000 --- a/src/video_core/gpu_synch.cpp +++ /dev/null | |||
| @@ -1,61 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/gpu_synch.h" | ||
| 6 | #include "video_core/renderer_base.h" | ||
| 7 | |||
| 8 | namespace VideoCommon { | ||
| 9 | |||
| 10 | GPUSynch::GPUSynch(Core::System& system_, bool use_nvdec_) : GPU{system_, false, use_nvdec_} {} | ||
| 11 | |||
| 12 | GPUSynch::~GPUSynch() = default; | ||
| 13 | |||
| 14 | void GPUSynch::Start() {} | ||
| 15 | |||
| 16 | void GPUSynch::ObtainContext() { | ||
| 17 | renderer->Context().MakeCurrent(); | ||
| 18 | } | ||
| 19 | |||
| 20 | void GPUSynch::ReleaseContext() { | ||
| 21 | renderer->Context().DoneCurrent(); | ||
| 22 | } | ||
| 23 | |||
| 24 | void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { | ||
| 25 | dma_pusher->Push(std::move(entries)); | ||
| 26 | dma_pusher->DispatchCalls(); | ||
| 27 | } | ||
| 28 | |||
| 29 | void GPUSynch::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { | ||
| 30 | if (!use_nvdec) { | ||
| 31 | return; | ||
| 32 | } | ||
| 33 | // This condition fires when a video stream ends, clears all intermediary data | ||
| 34 | if (entries[0].raw == 0xDEADB33F) { | ||
| 35 | cdma_pusher.reset(); | ||
| 36 | return; | ||
| 37 | } | ||
| 38 | if (!cdma_pusher) { | ||
| 39 | cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this); | ||
| 40 | } | ||
| 41 | cdma_pusher->Push(std::move(entries)); | ||
| 42 | cdma_pusher->DispatchCalls(); | ||
| 43 | } | ||
| 44 | |||
| 45 | void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||
| 46 | renderer->SwapBuffers(framebuffer); | ||
| 47 | } | ||
| 48 | |||
| 49 | void GPUSynch::FlushRegion(VAddr addr, u64 size) { | ||
| 50 | renderer->Rasterizer().FlushRegion(addr, size); | ||
| 51 | } | ||
| 52 | |||
| 53 | void GPUSynch::InvalidateRegion(VAddr addr, u64 size) { | ||
| 54 | renderer->Rasterizer().InvalidateRegion(addr, size); | ||
| 55 | } | ||
| 56 | |||
| 57 | void GPUSynch::FlushAndInvalidateRegion(VAddr addr, u64 size) { | ||
| 58 | renderer->Rasterizer().FlushAndInvalidateRegion(addr, size); | ||
| 59 | } | ||
| 60 | |||
| 61 | } // namespace VideoCommon | ||
diff --git a/src/video_core/gpu_synch.h b/src/video_core/gpu_synch.h deleted file mode 100644 index c5904b8db..000000000 --- a/src/video_core/gpu_synch.h +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "video_core/gpu.h" | ||
| 8 | |||
| 9 | namespace Core::Frontend { | ||
| 10 | class GraphicsContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace VideoCore { | ||
| 14 | class RendererBase; | ||
| 15 | } // namespace VideoCore | ||
| 16 | |||
| 17 | namespace VideoCommon { | ||
| 18 | |||
| 19 | /// Implementation of GPU interface that runs the GPU synchronously | ||
| 20 | class GPUSynch final : public Tegra::GPU { | ||
| 21 | public: | ||
| 22 | explicit GPUSynch(Core::System& system_, bool use_nvdec_); | ||
| 23 | ~GPUSynch() override; | ||
| 24 | |||
| 25 | void Start() override; | ||
| 26 | void ObtainContext() override; | ||
| 27 | void ReleaseContext() override; | ||
| 28 | void PushGPUEntries(Tegra::CommandList&& entries) override; | ||
| 29 | void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) override; | ||
| 30 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | ||
| 31 | void FlushRegion(VAddr addr, u64 size) override; | ||
| 32 | void InvalidateRegion(VAddr addr, u64 size) override; | ||
| 33 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||
| 34 | void WaitIdle() const override {} | ||
| 35 | |||
| 36 | protected: | ||
| 37 | void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, | ||
| 38 | [[maybe_unused]] u32 value) const override {} | ||
| 39 | }; | ||
| 40 | |||
| 41 | } // namespace VideoCommon | ||
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index f1c52cd9e..0071195d6 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -10,8 +10,9 @@ | |||
| 10 | #include <optional> | 10 | #include <optional> |
| 11 | #include <thread> | 11 | #include <thread> |
| 12 | #include <variant> | 12 | #include <variant> |
| 13 | |||
| 13 | #include "common/threadsafe_queue.h" | 14 | #include "common/threadsafe_queue.h" |
| 14 | #include "video_core/gpu.h" | 15 | #include "video_core/framebuffer_config.h" |
| 15 | 16 | ||
| 16 | namespace Tegra { | 17 | namespace Tegra { |
| 17 | struct FramebufferConfig; | 18 | struct FramebufferConfig; |
| @@ -25,6 +26,10 @@ class GraphicsContext; | |||
| 25 | class System; | 26 | class System; |
| 26 | } // namespace Core | 27 | } // namespace Core |
| 27 | 28 | ||
| 29 | namespace VideoCore { | ||
| 30 | class RendererBase; | ||
| 31 | } // namespace VideoCore | ||
| 32 | |||
| 28 | namespace VideoCommon::GPUThread { | 33 | namespace VideoCommon::GPUThread { |
| 29 | 34 | ||
| 30 | /// Command to signal to the GPU thread that processing has ended | 35 | /// Command to signal to the GPU thread that processing has ended |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 837800bfe..53444e945 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -7,8 +7,6 @@ | |||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/settings.h" | 9 | #include "core/settings.h" |
| 10 | #include "video_core/gpu_asynch.h" | ||
| 11 | #include "video_core/gpu_synch.h" | ||
| 12 | #include "video_core/renderer_base.h" | 10 | #include "video_core/renderer_base.h" |
| 13 | #include "video_core/renderer_opengl/renderer_opengl.h" | 11 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 14 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| @@ -39,13 +37,9 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer( | |||
| 39 | namespace VideoCore { | 37 | namespace VideoCore { |
| 40 | 38 | ||
| 41 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { | 39 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { |
| 42 | std::unique_ptr<Tegra::GPU> gpu; | ||
| 43 | const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); | 40 | const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); |
| 44 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | 41 | std::unique_ptr<Tegra::GPU> gpu = std::make_unique<Tegra::GPU>( |
| 45 | gpu = std::make_unique<VideoCommon::GPUAsynch>(system, use_nvdec); | 42 | system, Settings::values.use_asynchronous_gpu_emulation.GetValue(), use_nvdec); |
| 46 | } else { | ||
| 47 | gpu = std::make_unique<VideoCommon::GPUSynch>(system, use_nvdec); | ||
| 48 | } | ||
| 49 | 43 | ||
| 50 | auto context = emu_window.CreateSharedContext(); | 44 | auto context = emu_window.CreateSharedContext(); |
| 51 | const auto scope = context->Acquire(); | 45 | const auto scope = context->Acquire(); |