Browse Source
video_core: gpu: Refactor out synchronous/asynchronous GPU implementations.
video_core: gpu: Refactor out synchronous/asynchronous GPU implementations.
- We must always use a GPU thread now, even with synchronous GPU.nce_cpp
10 changed files with 130 additions and 289 deletions
-
5src/video_core/CMakeLists.txt
-
31src/video_core/framebuffer_config.h
-
76src/video_core/gpu.cpp
-
55src/video_core/gpu.h
-
86src/video_core/gpu_asynch.cpp
-
47src/video_core/gpu_asynch.h
-
61src/video_core/gpu_synch.cpp
-
41src/video_core/gpu_synch.h
-
7src/video_core/gpu_thread.h
-
10src/video_core/video_core.cpp
@ -0,0 +1,31 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
namespace Tegra { |
||||
|
|
||||
|
/** |
||||
|
* Struct describing framebuffer configuration |
||||
|
*/ |
||||
|
struct FramebufferConfig { |
||||
|
enum class PixelFormat : u32 { |
||||
|
A8B8G8R8_UNORM = 1, |
||||
|
RGB565_UNORM = 4, |
||||
|
B8G8R8A8_UNORM = 5, |
||||
|
}; |
||||
|
|
||||
|
VAddr address{}; |
||||
|
u32 offset{}; |
||||
|
u32 width{}; |
||||
|
u32 height{}; |
||||
|
u32 stride{}; |
||||
|
PixelFormat pixel_format{}; |
||||
|
|
||||
|
using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags; |
||||
|
TransformFlags transform_flags{}; |
||||
|
Common::Rectangle<int> crop_rect; |
||||
|
}; |
||||
|
|
||||
|
} // namespace Tegra |
||||
@ -1,86 +0,0 @@ |
|||||
// Copyright 2019 yuzu Emulator Project
|
|
||||
// Licensed under GPLv2 or any later version
|
|
||||
// Refer to the license.txt file included.
|
|
||||
|
|
||||
#include "core/core.h"
|
|
||||
#include "core/hardware_interrupt_manager.h"
|
|
||||
#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_, bool use_nvdec_) |
|
||||
: GPU{system_, true, use_nvdec_}, gpu_thread{system_} {} |
|
||||
|
|
||||
GPUAsynch::~GPUAsynch() = default; |
|
||||
|
|
||||
void GPUAsynch::Start() { |
|
||||
gpu_thread.StartThread(*renderer, renderer->Context(), *dma_pusher, *cdma_pusher); |
|
||||
cpu_context = renderer->GetRenderWindow().CreateSharedContext(); |
|
||||
cpu_context->MakeCurrent(); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::ObtainContext() { |
|
||||
cpu_context->MakeCurrent(); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::ReleaseContext() { |
|
||||
cpu_context->DoneCurrent(); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::PushGPUEntries(Tegra::CommandList&& entries) { |
|
||||
gpu_thread.SubmitList(std::move(entries)); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { |
|
||||
if (!use_nvdec) { |
|
||||
return; |
|
||||
} |
|
||||
// This condition fires when a video stream ends, clear all intermediary data
|
|
||||
if (entries[0].raw == 0xDEADB33F) { |
|
||||
cdma_pusher.reset(); |
|
||||
return; |
|
||||
} |
|
||||
if (!cdma_pusher) { |
|
||||
cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this); |
|
||||
} |
|
||||
|
|
||||
// SubmitCommandBuffer would make the nvdec operations async, this is not currently working
|
|
||||
// TODO(ameerj): RE proper async nvdec operation
|
|
||||
// gpu_thread.SubmitCommandBuffer(std::move(entries));
|
|
||||
|
|
||||
cdma_pusher->Push(std::move(entries)); |
|
||||
cdma_pusher->DispatchCalls(); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
|
||||
gpu_thread.SwapBuffers(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); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { |
|
||||
auto& interrupt_manager = system.InterruptManager(); |
|
||||
interrupt_manager.GPUInterruptSyncpt(syncpoint_id, value); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::WaitIdle() const { |
|
||||
gpu_thread.WaitIdle(); |
|
||||
} |
|
||||
|
|
||||
void GPUAsynch::OnCommandListEnd() { |
|
||||
gpu_thread.OnCommandListEnd(); |
|
||||
} |
|
||||
|
|
||||
} // namespace VideoCommon
|
|
||||
@ -1,47 +0,0 @@ |
|||||
// 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 Core::Frontend { |
|
||||
class GraphicsContext; |
|
||||
} |
|
||||
|
|
||||
namespace VideoCore { |
|
||||
class RendererBase; |
|
||||
} // namespace VideoCore |
|
||||
|
|
||||
namespace VideoCommon { |
|
||||
|
|
||||
/// Implementation of GPU interface that runs the GPU asynchronously |
|
||||
class GPUAsynch final : public Tegra::GPU { |
|
||||
public: |
|
||||
explicit GPUAsynch(Core::System& system_, bool use_nvdec_); |
|
||||
~GPUAsynch() override; |
|
||||
|
|
||||
void Start() override; |
|
||||
void ObtainContext() override; |
|
||||
void ReleaseContext() override; |
|
||||
void PushGPUEntries(Tegra::CommandList&& entries) override; |
|
||||
void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) override; |
|
||||
void SwapBuffers(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; |
|
||||
void WaitIdle() const override; |
|
||||
|
|
||||
void OnCommandListEnd() override; |
|
||||
|
|
||||
protected: |
|
||||
void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const override; |
|
||||
|
|
||||
private: |
|
||||
GPUThread::ThreadManager gpu_thread; |
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context; |
|
||||
}; |
|
||||
|
|
||||
} // namespace VideoCommon |
|
||||
@ -1,61 +0,0 @@ |
|||||
// 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_, bool use_nvdec_) : GPU{system_, false, use_nvdec_} {} |
|
||||
|
|
||||
GPUSynch::~GPUSynch() = default; |
|
||||
|
|
||||
void GPUSynch::Start() {} |
|
||||
|
|
||||
void GPUSynch::ObtainContext() { |
|
||||
renderer->Context().MakeCurrent(); |
|
||||
} |
|
||||
|
|
||||
void GPUSynch::ReleaseContext() { |
|
||||
renderer->Context().DoneCurrent(); |
|
||||
} |
|
||||
|
|
||||
void GPUSynch::PushGPUEntries(Tegra::CommandList&& entries) { |
|
||||
dma_pusher->Push(std::move(entries)); |
|
||||
dma_pusher->DispatchCalls(); |
|
||||
} |
|
||||
|
|
||||
void GPUSynch::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { |
|
||||
if (!use_nvdec) { |
|
||||
return; |
|
||||
} |
|
||||
// This condition fires when a video stream ends, clears all intermediary data
|
|
||||
if (entries[0].raw == 0xDEADB33F) { |
|
||||
cdma_pusher.reset(); |
|
||||
return; |
|
||||
} |
|
||||
if (!cdma_pusher) { |
|
||||
cdma_pusher = std::make_unique<Tegra::CDmaPusher>(*this); |
|
||||
} |
|
||||
cdma_pusher->Push(std::move(entries)); |
|
||||
cdma_pusher->DispatchCalls(); |
|
||||
} |
|
||||
|
|
||||
void GPUSynch::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
|
||||
renderer->SwapBuffers(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
|
|
||||
@ -1,41 +0,0 @@ |
|||||
// 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 Core::Frontend { |
|
||||
class GraphicsContext; |
|
||||
} |
|
||||
|
|
||||
namespace VideoCore { |
|
||||
class RendererBase; |
|
||||
} // namespace VideoCore |
|
||||
|
|
||||
namespace VideoCommon { |
|
||||
|
|
||||
/// Implementation of GPU interface that runs the GPU synchronously |
|
||||
class GPUSynch final : public Tegra::GPU { |
|
||||
public: |
|
||||
explicit GPUSynch(Core::System& system_, bool use_nvdec_); |
|
||||
~GPUSynch() override; |
|
||||
|
|
||||
void Start() override; |
|
||||
void ObtainContext() override; |
|
||||
void ReleaseContext() override; |
|
||||
void PushGPUEntries(Tegra::CommandList&& entries) override; |
|
||||
void PushCommandBuffer(Tegra::ChCommandHeaderList& entries) override; |
|
||||
void SwapBuffers(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; |
|
||||
void WaitIdle() const override {} |
|
||||
|
|
||||
protected: |
|
||||
void TriggerCpuInterrupt([[maybe_unused]] u32 syncpoint_id, |
|
||||
[[maybe_unused]] u32 value) const override {} |
|
||||
}; |
|
||||
|
|
||||
} // namespace VideoCommon |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue