diff options
| author | 2021-01-05 04:09:39 -0300 | |
|---|---|---|
| committer | 2021-02-13 02:16:19 -0300 | |
| commit | 75ccd9959ca7aa78b71fbb800ed2127d8613e9dc (patch) | |
| tree | 3b9b5c0779cff69ef135bb3394ae70a0d3a9804d | |
| parent | tests/buffer_base: Add cached CPU writes tests (diff) | |
| download | yuzu-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.tar.gz yuzu-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.tar.xz yuzu-75ccd9959ca7aa78b71fbb800ed2127d8613e9dc.zip | |
gpu: Report renderer errors with exceptions
Instead of using a two step initialization to report errors, initialize
the GPU renderer and rasterizer on the constructor and report errors
through std::runtime_error.
27 files changed, 176 insertions, 232 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index a01d334ad..0f640fdae 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -18,8 +18,8 @@ Fermi2D::Fermi2D() { | |||
| 18 | 18 | ||
| 19 | Fermi2D::~Fermi2D() = default; | 19 | Fermi2D::~Fermi2D() = default; |
| 20 | 20 | ||
| 21 | void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | 21 | void Fermi2D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { |
| 22 | rasterizer = &rasterizer_; | 22 | rasterizer = rasterizer_; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 25 | void Fermi2D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 0de3280a2..c808a577d 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -38,7 +38,7 @@ public: | |||
| 38 | ~Fermi2D(); | 38 | ~Fermi2D(); |
| 39 | 39 | ||
| 40 | /// Binds a rasterizer to this engine. | 40 | /// Binds a rasterizer to this engine. |
| 41 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | 41 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 42 | 42 | ||
| 43 | /// Write the value to the register identified by method. | 43 | /// Write the value to the register identified by method. |
| 44 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; | 44 | void CallMethod(u32 method, u32 method_argument, bool is_last_call) override; |
diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index ba387506e..ed29fc7ac 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp | |||
| @@ -21,8 +21,8 @@ KeplerCompute::KeplerCompute(Core::System& system_, MemoryManager& memory_manage | |||
| 21 | 21 | ||
| 22 | KeplerCompute::~KeplerCompute() = default; | 22 | KeplerCompute::~KeplerCompute() = default; |
| 23 | 23 | ||
| 24 | void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | 24 | void KeplerCompute::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { |
| 25 | rasterizer = &rasterizer_; | 25 | rasterizer = rasterizer_; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 28 | void KeplerCompute::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index 9f0a7b76d..7c40cba38 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h | |||
| @@ -46,7 +46,7 @@ public: | |||
| 46 | ~KeplerCompute(); | 46 | ~KeplerCompute(); |
| 47 | 47 | ||
| 48 | /// Binds a rasterizer to this engine. | 48 | /// Binds a rasterizer to this engine. |
| 49 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | 49 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 50 | 50 | ||
| 51 | static constexpr std::size_t NumConstBuffers = 8; | 51 | static constexpr std::size_t NumConstBuffers = 8; |
| 52 | 52 | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 116ad1722..d6ba9da5c 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -30,8 +30,8 @@ Maxwell3D::Maxwell3D(Core::System& system_, MemoryManager& memory_manager_) | |||
| 30 | 30 | ||
| 31 | Maxwell3D::~Maxwell3D() = default; | 31 | Maxwell3D::~Maxwell3D() = default; |
| 32 | 32 | ||
| 33 | void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | 33 | void Maxwell3D::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { |
| 34 | rasterizer = &rasterizer_; | 34 | rasterizer = rasterizer_; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void Maxwell3D::InitializeRegisterDefaults() { | 37 | void Maxwell3D::InitializeRegisterDefaults() { |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 002d1b3f9..cc94d2678 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -55,7 +55,7 @@ public: | |||
| 55 | ~Maxwell3D(); | 55 | ~Maxwell3D(); |
| 56 | 56 | ||
| 57 | /// Binds a rasterizer to this engine. | 57 | /// Binds a rasterizer to this engine. |
| 58 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | 58 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 59 | 59 | ||
| 60 | /// Register structure of the Maxwell3D engine. | 60 | /// Register structure of the Maxwell3D engine. |
| 61 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. | 61 | /// TODO(Subv): This structure will need to be made bigger as more registers are discovered. |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 6ab06775f..2a9bd4121 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -44,8 +44,8 @@ GPU::~GPU() = default; | |||
| 44 | 44 | ||
| 45 | void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { | 45 | void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { |
| 46 | renderer = std::move(renderer_); | 46 | renderer = std::move(renderer_); |
| 47 | rasterizer = renderer->ReadRasterizer(); | ||
| 47 | 48 | ||
| 48 | VideoCore::RasterizerInterface& rasterizer = renderer->Rasterizer(); | ||
| 49 | memory_manager->BindRasterizer(rasterizer); | 49 | memory_manager->BindRasterizer(rasterizer); |
| 50 | maxwell_3d->BindRasterizer(rasterizer); | 50 | maxwell_3d->BindRasterizer(rasterizer); |
| 51 | fermi_2d->BindRasterizer(rasterizer); | 51 | fermi_2d->BindRasterizer(rasterizer); |
| @@ -171,7 +171,7 @@ void GPU::TickWork() { | |||
| 171 | const std::size_t size = request.size; | 171 | const std::size_t size = request.size; |
| 172 | flush_requests.pop_front(); | 172 | flush_requests.pop_front(); |
| 173 | flush_request_mutex.unlock(); | 173 | flush_request_mutex.unlock(); |
| 174 | renderer->Rasterizer().FlushRegion(addr, size); | 174 | rasterizer->FlushRegion(addr, size); |
| 175 | current_flush_fence.store(fence); | 175 | current_flush_fence.store(fence); |
| 176 | flush_request_mutex.lock(); | 176 | flush_request_mutex.lock(); |
| 177 | } | 177 | } |
| @@ -193,11 +193,11 @@ u64 GPU::GetTicks() const { | |||
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | void GPU::FlushCommands() { | 195 | void GPU::FlushCommands() { |
| 196 | renderer->Rasterizer().FlushCommands(); | 196 | rasterizer->FlushCommands(); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | void GPU::SyncGuestHost() { | 199 | void GPU::SyncGuestHost() { |
| 200 | renderer->Rasterizer().SyncGuestHost(); | 200 | rasterizer->SyncGuestHost(); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | enum class GpuSemaphoreOperation { | 203 | enum class GpuSemaphoreOperation { |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index b4ce6b154..b2ee45496 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -366,6 +366,7 @@ protected: | |||
| 366 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; | 366 | std::unique_ptr<Tegra::DmaPusher> dma_pusher; |
| 367 | std::unique_ptr<Tegra::CDmaPusher> cdma_pusher; | 367 | std::unique_ptr<Tegra::CDmaPusher> cdma_pusher; |
| 368 | std::unique_ptr<VideoCore::RendererBase> renderer; | 368 | std::unique_ptr<VideoCore::RendererBase> renderer; |
| 369 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 369 | const bool use_nvdec; | 370 | const bool use_nvdec; |
| 370 | 371 | ||
| 371 | private: | 372 | private: |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 7e490bcc3..50319f1d5 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -38,6 +38,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, | |||
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | auto current_context = context.Acquire(); | 40 | auto current_context = context.Acquire(); |
| 41 | VideoCore::RasterizerInterface* const rasterizer = renderer.ReadRasterizer(); | ||
| 41 | 42 | ||
| 42 | CommandDataContainer next; | 43 | CommandDataContainer next; |
| 43 | while (state.is_running) { | 44 | while (state.is_running) { |
| @@ -52,13 +53,13 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, | |||
| 52 | } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) { | 53 | } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) { |
| 53 | renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); | 54 | renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); |
| 54 | } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) { | 55 | } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) { |
| 55 | renderer.Rasterizer().ReleaseFences(); | 56 | rasterizer->ReleaseFences(); |
| 56 | } else if (std::holds_alternative<GPUTickCommand>(next.data)) { | 57 | } else if (std::holds_alternative<GPUTickCommand>(next.data)) { |
| 57 | system.GPU().TickWork(); | 58 | system.GPU().TickWork(); |
| 58 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { | 59 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { |
| 59 | renderer.Rasterizer().FlushRegion(flush->addr, flush->size); | 60 | rasterizer->FlushRegion(flush->addr, flush->size); |
| 60 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { | 61 | } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { |
| 61 | renderer.Rasterizer().OnCPUWrite(invalidate->addr, invalidate->size); | 62 | rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); |
| 62 | } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { | 63 | } else if (std::holds_alternative<EndProcessingCommand>(next.data)) { |
| 63 | return; | 64 | return; |
| 64 | } else { | 65 | } else { |
| @@ -84,6 +85,7 @@ ThreadManager::~ThreadManager() { | |||
| 84 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, | 85 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, |
| 85 | Core::Frontend::GraphicsContext& context, | 86 | Core::Frontend::GraphicsContext& context, |
| 86 | Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) { | 87 | Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher) { |
| 88 | rasterizer = renderer.ReadRasterizer(); | ||
| 87 | thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), | 89 | thread = std::thread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), |
| 88 | std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher)); | 90 | std::ref(dma_pusher), std::ref(state), std::ref(cdma_pusher)); |
| 89 | } | 91 | } |
| @@ -129,12 +131,12 @@ void ThreadManager::FlushRegion(VAddr addr, u64 size) { | |||
| 129 | } | 131 | } |
| 130 | 132 | ||
| 131 | void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { | 133 | void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { |
| 132 | system.Renderer().Rasterizer().OnCPUWrite(addr, size); | 134 | rasterizer->OnCPUWrite(addr, size); |
| 133 | } | 135 | } |
| 134 | 136 | ||
| 135 | void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { | 137 | void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { |
| 136 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important | 138 | // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important |
| 137 | system.Renderer().Rasterizer().OnCPUWrite(addr, size); | 139 | rasterizer->OnCPUWrite(addr, size); |
| 138 | } | 140 | } |
| 139 | 141 | ||
| 140 | void ThreadManager::WaitIdle() const { | 142 | void ThreadManager::WaitIdle() const { |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 2775629e7..4cd951169 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -27,6 +27,7 @@ class System; | |||
| 27 | } // namespace Core | 27 | } // namespace Core |
| 28 | 28 | ||
| 29 | namespace VideoCore { | 29 | namespace VideoCore { |
| 30 | class RasterizerInterface; | ||
| 30 | class RendererBase; | 31 | class RendererBase; |
| 31 | } // namespace VideoCore | 32 | } // namespace VideoCore |
| 32 | 33 | ||
| @@ -151,11 +152,12 @@ private: | |||
| 151 | /// Pushes a command to be executed by the GPU thread | 152 | /// Pushes a command to be executed by the GPU thread |
| 152 | u64 PushCommand(CommandData&& command_data); | 153 | u64 PushCommand(CommandData&& command_data); |
| 153 | 154 | ||
| 154 | SynchState state; | ||
| 155 | Core::System& system; | 155 | Core::System& system; |
| 156 | std::thread thread; | ||
| 157 | std::thread::id thread_id; | ||
| 158 | const bool is_async; | 156 | const bool is_async; |
| 157 | VideoCore::RasterizerInterface* rasterizer = nullptr; | ||
| 158 | |||
| 159 | SynchState state; | ||
| 160 | std::thread thread; | ||
| 159 | }; | 161 | }; |
| 160 | 162 | ||
| 161 | } // namespace VideoCommon::GPUThread | 163 | } // namespace VideoCommon::GPUThread |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index c841f3cd7..44240a9c4 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -21,8 +21,8 @@ MemoryManager::MemoryManager(Core::System& system_) | |||
| 21 | 21 | ||
| 22 | MemoryManager::~MemoryManager() = default; | 22 | MemoryManager::~MemoryManager() = default; |
| 23 | 23 | ||
| 24 | void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface& rasterizer_) { | 24 | void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { |
| 25 | rasterizer = &rasterizer_; | 25 | rasterizer = rasterizer_; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { | 28 | GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std::size_t size) { |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index b468a67de..5d963eba6 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -72,7 +72,7 @@ public: | |||
| 72 | ~MemoryManager(); | 72 | ~MemoryManager(); |
| 73 | 73 | ||
| 74 | /// Binds a renderer to the memory manager. | 74 | /// Binds a renderer to the memory manager. |
| 75 | void BindRasterizer(VideoCore::RasterizerInterface& rasterizer); | 75 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 76 | 76 | ||
| 77 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; | 77 | [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; |
| 78 | 78 | ||
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 51dde8eb5..320ee8d30 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -37,15 +37,11 @@ public: | |||
| 37 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | 37 | std::unique_ptr<Core::Frontend::GraphicsContext> context); |
| 38 | virtual ~RendererBase(); | 38 | virtual ~RendererBase(); |
| 39 | 39 | ||
| 40 | /// Initialize the renderer | ||
| 41 | [[nodiscard]] virtual bool Init() = 0; | ||
| 42 | |||
| 43 | /// Shutdown the renderer | ||
| 44 | virtual void ShutDown() = 0; | ||
| 45 | |||
| 46 | /// Finalize rendering the guest frame and draw into the presentation texture | 40 | /// Finalize rendering the guest frame and draw into the presentation texture |
| 47 | virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0; | 41 | virtual void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) = 0; |
| 48 | 42 | ||
| 43 | [[nodiscard]] virtual RasterizerInterface* ReadRasterizer() = 0; | ||
| 44 | |||
| 49 | // Getter/setter functions: | 45 | // Getter/setter functions: |
| 50 | // ------------------------ | 46 | // ------------------------ |
| 51 | 47 | ||
| @@ -57,14 +53,6 @@ public: | |||
| 57 | return m_current_frame; | 53 | return m_current_frame; |
| 58 | } | 54 | } |
| 59 | 55 | ||
| 60 | [[nodiscard]] RasterizerInterface& Rasterizer() { | ||
| 61 | return *rasterizer; | ||
| 62 | } | ||
| 63 | |||
| 64 | [[nodiscard]] const RasterizerInterface& Rasterizer() const { | ||
| 65 | return *rasterizer; | ||
| 66 | } | ||
| 67 | |||
| 68 | [[nodiscard]] Core::Frontend::GraphicsContext& Context() { | 56 | [[nodiscard]] Core::Frontend::GraphicsContext& Context() { |
| 69 | return *context; | 57 | return *context; |
| 70 | } | 58 | } |
| @@ -98,7 +86,6 @@ public: | |||
| 98 | 86 | ||
| 99 | protected: | 87 | protected: |
| 100 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. | 88 | Core::Frontend::EmuWindow& render_window; ///< Reference to the render window handle. |
| 101 | std::unique_ptr<RasterizerInterface> rasterizer; | ||
| 102 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | 89 | std::unique_ptr<Core::Frontend::GraphicsContext> context; |
| 103 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer | 90 | f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer |
| 104 | int m_current_frame = 0; ///< Current frame, should be set by the renderer | 91 | int m_current_frame = 0; ///< Current frame, should be set by the renderer |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 21159e498..7eb5ab17a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -132,7 +132,20 @@ RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, | |||
| 132 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 132 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, |
| 133 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 133 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) |
| 134 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, | 134 | : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, |
| 135 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device} {} | 135 | emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, program_manager{device}, |
| 136 | rasterizer{emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker} { | ||
| 137 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | ||
| 138 | glEnable(GL_DEBUG_OUTPUT); | ||
| 139 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | ||
| 140 | glDebugMessageCallback(DebugHandler, nullptr); | ||
| 141 | } | ||
| 142 | AddTelemetryFields(); | ||
| 143 | |||
| 144 | if (!GLAD_GL_VERSION_4_6) { | ||
| 145 | throw std::runtime_error{"OpenGL 4.3 is not available"}; | ||
| 146 | } | ||
| 147 | InitOpenGLObjects(); | ||
| 148 | } | ||
| 136 | 149 | ||
| 137 | RendererOpenGL::~RendererOpenGL() = default; | 150 | RendererOpenGL::~RendererOpenGL() = default; |
| 138 | 151 | ||
| @@ -148,7 +161,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 148 | 161 | ||
| 149 | ++m_current_frame; | 162 | ++m_current_frame; |
| 150 | 163 | ||
| 151 | rasterizer->TickFrame(); | 164 | rasterizer.TickFrame(); |
| 152 | 165 | ||
| 153 | context->SwapBuffers(); | 166 | context->SwapBuffers(); |
| 154 | render_window.OnFrameDisplayed(); | 167 | render_window.OnFrameDisplayed(); |
| @@ -179,7 +192,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf | |||
| 179 | framebuffer_crop_rect = framebuffer.crop_rect; | 192 | framebuffer_crop_rect = framebuffer.crop_rect; |
| 180 | 193 | ||
| 181 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; | 194 | const VAddr framebuffer_addr{framebuffer.address + framebuffer.offset}; |
| 182 | if (rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) { | 195 | if (rasterizer.AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride)) { |
| 183 | return; | 196 | return; |
| 184 | } | 197 | } |
| 185 | 198 | ||
| @@ -289,14 +302,6 @@ void RendererOpenGL::AddTelemetryFields() { | |||
| 289 | telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); | 302 | telemetry_session.AddField(user_system, "GPU_OpenGL_Version", std::string(gl_version)); |
| 290 | } | 303 | } |
| 291 | 304 | ||
| 292 | void RendererOpenGL::CreateRasterizer() { | ||
| 293 | if (rasterizer) { | ||
| 294 | return; | ||
| 295 | } | ||
| 296 | rasterizer = std::make_unique<RasterizerOpenGL>(emu_window, gpu, cpu_memory, device, | ||
| 297 | screen_info, program_manager, state_tracker); | ||
| 298 | } | ||
| 299 | |||
| 300 | void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | 305 | void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, |
| 301 | const Tegra::FramebufferConfig& framebuffer) { | 306 | const Tegra::FramebufferConfig& framebuffer) { |
| 302 | texture.width = framebuffer.width; | 307 | texture.width = framebuffer.width; |
| @@ -497,25 +502,4 @@ void RendererOpenGL::RenderScreenshot() { | |||
| 497 | renderer_settings.screenshot_requested = false; | 502 | renderer_settings.screenshot_requested = false; |
| 498 | } | 503 | } |
| 499 | 504 | ||
| 500 | bool RendererOpenGL::Init() { | ||
| 501 | if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { | ||
| 502 | glEnable(GL_DEBUG_OUTPUT); | ||
| 503 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); | ||
| 504 | glDebugMessageCallback(DebugHandler, nullptr); | ||
| 505 | } | ||
| 506 | |||
| 507 | AddTelemetryFields(); | ||
| 508 | |||
| 509 | if (!GLAD_GL_VERSION_4_6) { | ||
| 510 | return false; | ||
| 511 | } | ||
| 512 | |||
| 513 | InitOpenGLObjects(); | ||
| 514 | CreateRasterizer(); | ||
| 515 | |||
| 516 | return true; | ||
| 517 | } | ||
| 518 | |||
| 519 | void RendererOpenGL::ShutDown() {} | ||
| 520 | |||
| 521 | } // namespace OpenGL | 505 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 44e109794..e043a0ccb 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/math_util.h" | 10 | #include "common/math_util.h" |
| 11 | #include "video_core/renderer_base.h" | 11 | #include "video_core/renderer_base.h" |
| 12 | #include "video_core/renderer_opengl/gl_device.h" | 12 | #include "video_core/renderer_opengl/gl_device.h" |
| 13 | #include "video_core/renderer_opengl/gl_rasterizer.h" | ||
| 13 | #include "video_core/renderer_opengl/gl_resource_manager.h" | 14 | #include "video_core/renderer_opengl/gl_resource_manager.h" |
| 14 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 15 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 15 | #include "video_core/renderer_opengl/gl_state_tracker.h" | 16 | #include "video_core/renderer_opengl/gl_state_tracker.h" |
| @@ -63,18 +64,18 @@ public: | |||
| 63 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); | 64 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); |
| 64 | ~RendererOpenGL() override; | 65 | ~RendererOpenGL() override; |
| 65 | 66 | ||
| 66 | bool Init() override; | ||
| 67 | void ShutDown() override; | ||
| 68 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | 67 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; |
| 69 | 68 | ||
| 69 | VideoCore::RasterizerInterface* ReadRasterizer() override { | ||
| 70 | return &rasterizer; | ||
| 71 | } | ||
| 72 | |||
| 70 | private: | 73 | private: |
| 71 | /// Initializes the OpenGL state and creates persistent objects. | 74 | /// Initializes the OpenGL state and creates persistent objects. |
| 72 | void InitOpenGLObjects(); | 75 | void InitOpenGLObjects(); |
| 73 | 76 | ||
| 74 | void AddTelemetryFields(); | 77 | void AddTelemetryFields(); |
| 75 | 78 | ||
| 76 | void CreateRasterizer(); | ||
| 77 | |||
| 78 | void ConfigureFramebufferTexture(TextureInfo& texture, | 79 | void ConfigureFramebufferTexture(TextureInfo& texture, |
| 79 | const Tegra::FramebufferConfig& framebuffer); | 80 | const Tegra::FramebufferConfig& framebuffer); |
| 80 | 81 | ||
| @@ -118,6 +119,8 @@ private: | |||
| 118 | /// Global dummy shader pipeline | 119 | /// Global dummy shader pipeline |
| 119 | ProgramManager program_manager; | 120 | ProgramManager program_manager; |
| 120 | 121 | ||
| 122 | RasterizerOpenGL rasterizer; | ||
| 123 | |||
| 121 | /// OpenGL framebuffer data | 124 | /// OpenGL framebuffer data |
| 122 | std::vector<u8> gl_framebuffer_data; | 125 | std::vector<u8> gl_framebuffer_data; |
| 123 | 126 | ||
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 61796e33a..6909576cb 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -80,17 +80,50 @@ std::string BuildCommaSeparatedExtensions(std::vector<std::string> available_ext | |||
| 80 | return separated_extensions; | 80 | return separated_extensions; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dld, | ||
| 84 | VkSurfaceKHR surface) { | ||
| 85 | const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices(); | ||
| 86 | const s32 device_index = Settings::values.vulkan_device.GetValue(); | ||
| 87 | if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) { | ||
| 88 | LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); | ||
| 89 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | ||
| 90 | } | ||
| 91 | const vk::PhysicalDevice physical_device(devices[device_index], dld); | ||
| 92 | return Device(*instance, physical_device, surface, dld); | ||
| 93 | } | ||
| 83 | } // Anonymous namespace | 94 | } // Anonymous namespace |
| 84 | 95 | ||
| 85 | RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | 96 | RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, |
| 86 | Core::Frontend::EmuWindow& emu_window, | 97 | Core::Frontend::EmuWindow& emu_window, |
| 87 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, | 98 | Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, |
| 88 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | 99 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) try |
| 89 | : RendererBase{emu_window, std::move(context_)}, telemetry_session{telemetry_session_}, | 100 | : RendererBase(emu_window, std::move(context_)), |
| 90 | cpu_memory{cpu_memory_}, gpu{gpu_} {} | 101 | telemetry_session(telemetry_session_), |
| 102 | cpu_memory(cpu_memory_), | ||
| 103 | gpu(gpu_), | ||
| 104 | library(OpenLibrary()), | ||
| 105 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | ||
| 106 | true, Settings::values.renderer_debug)), | ||
| 107 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | ||
| 108 | surface(CreateSurface(instance, render_window)), | ||
| 109 | device(CreateDevice(instance, dld, *surface)), | ||
| 110 | memory_allocator(device), | ||
| 111 | state_tracker(gpu), | ||
| 112 | scheduler(device, state_tracker), | ||
| 113 | swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width, | ||
| 114 | render_window.GetFramebufferLayout().height, false), | ||
| 115 | blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, scheduler, | ||
| 116 | screen_info), | ||
| 117 | rasterizer(render_window, gpu, gpu.MemoryManager(), cpu_memory, screen_info, device, | ||
| 118 | memory_allocator, state_tracker, scheduler) { | ||
| 119 | Report(); | ||
| 120 | } catch (const vk::Exception& exception) { | ||
| 121 | LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what()); | ||
| 122 | throw std::runtime_error{fmt::format("Vulkan initialization error {}", exception.what())}; | ||
| 123 | } | ||
| 91 | 124 | ||
| 92 | RendererVulkan::~RendererVulkan() { | 125 | RendererVulkan::~RendererVulkan() { |
| 93 | ShutDown(); | 126 | void(device.GetLogical().WaitIdle()); |
| 94 | } | 127 | } |
| 95 | 128 | ||
| 96 | void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | 129 | void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { |
| @@ -101,101 +134,38 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 101 | if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) { | 134 | if (layout.width > 0 && layout.height > 0 && render_window.IsShown()) { |
| 102 | const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; | 135 | const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; |
| 103 | const bool use_accelerated = | 136 | const bool use_accelerated = |
| 104 | rasterizer->AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); | 137 | rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); |
| 105 | const bool is_srgb = use_accelerated && screen_info.is_srgb; | 138 | const bool is_srgb = use_accelerated && screen_info.is_srgb; |
| 106 | if (swapchain->HasFramebufferChanged(layout) || swapchain->GetSrgbState() != is_srgb) { | 139 | if (swapchain.HasFramebufferChanged(layout) || swapchain.GetSrgbState() != is_srgb) { |
| 107 | swapchain->Create(layout.width, layout.height, is_srgb); | 140 | swapchain.Create(layout.width, layout.height, is_srgb); |
| 108 | blit_screen->Recreate(); | 141 | blit_screen.Recreate(); |
| 109 | } | 142 | } |
| 110 | 143 | ||
| 111 | scheduler->WaitWorker(); | 144 | scheduler.WaitWorker(); |
| 112 | 145 | ||
| 113 | swapchain->AcquireNextImage(); | 146 | swapchain.AcquireNextImage(); |
| 114 | const VkSemaphore render_semaphore = blit_screen->Draw(*framebuffer, use_accelerated); | 147 | const VkSemaphore render_semaphore = blit_screen.Draw(*framebuffer, use_accelerated); |
| 115 | 148 | ||
| 116 | scheduler->Flush(render_semaphore); | 149 | scheduler.Flush(render_semaphore); |
| 117 | 150 | ||
| 118 | if (swapchain->Present(render_semaphore)) { | 151 | if (swapchain.Present(render_semaphore)) { |
| 119 | blit_screen->Recreate(); | 152 | blit_screen.Recreate(); |
| 120 | } | 153 | } |
| 121 | 154 | rasterizer.TickFrame(); | |
| 122 | rasterizer->TickFrame(); | ||
| 123 | } | 155 | } |
| 124 | 156 | ||
| 125 | render_window.OnFrameDisplayed(); | 157 | render_window.OnFrameDisplayed(); |
| 126 | } | 158 | } |
| 127 | 159 | ||
| 128 | bool RendererVulkan::Init() try { | ||
| 129 | library = OpenLibrary(); | ||
| 130 | instance = CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | ||
| 131 | true, Settings::values.renderer_debug); | ||
| 132 | if (Settings::values.renderer_debug) { | ||
| 133 | debug_callback = CreateDebugCallback(instance); | ||
| 134 | } | ||
| 135 | surface = CreateSurface(instance, render_window); | ||
| 136 | |||
| 137 | InitializeDevice(); | ||
| 138 | Report(); | ||
| 139 | |||
| 140 | memory_allocator = std::make_unique<MemoryAllocator>(*device); | ||
| 141 | |||
| 142 | state_tracker = std::make_unique<StateTracker>(gpu); | ||
| 143 | |||
| 144 | scheduler = std::make_unique<VKScheduler>(*device, *state_tracker); | ||
| 145 | |||
| 146 | const auto& framebuffer = render_window.GetFramebufferLayout(); | ||
| 147 | swapchain = std::make_unique<VKSwapchain>(*surface, *device, *scheduler); | ||
| 148 | swapchain->Create(framebuffer.width, framebuffer.height, false); | ||
| 149 | |||
| 150 | rasterizer = std::make_unique<RasterizerVulkan>(render_window, gpu, gpu.MemoryManager(), | ||
| 151 | cpu_memory, screen_info, *device, | ||
| 152 | *memory_allocator, *state_tracker, *scheduler); | ||
| 153 | |||
| 154 | blit_screen = | ||
| 155 | std::make_unique<VKBlitScreen>(cpu_memory, render_window, *rasterizer, *device, | ||
| 156 | *memory_allocator, *swapchain, *scheduler, screen_info); | ||
| 157 | return true; | ||
| 158 | |||
| 159 | } catch (const vk::Exception& exception) { | ||
| 160 | LOG_ERROR(Render_Vulkan, "Vulkan initialization failed with error: {}", exception.what()); | ||
| 161 | return false; | ||
| 162 | } | ||
| 163 | |||
| 164 | void RendererVulkan::ShutDown() { | ||
| 165 | if (!device) { | ||
| 166 | return; | ||
| 167 | } | ||
| 168 | if (const auto& dev = device->GetLogical()) { | ||
| 169 | dev.WaitIdle(); | ||
| 170 | } | ||
| 171 | rasterizer.reset(); | ||
| 172 | blit_screen.reset(); | ||
| 173 | scheduler.reset(); | ||
| 174 | swapchain.reset(); | ||
| 175 | memory_allocator.reset(); | ||
| 176 | device.reset(); | ||
| 177 | } | ||
| 178 | |||
| 179 | void RendererVulkan::InitializeDevice() { | ||
| 180 | const std::vector<VkPhysicalDevice> devices = instance.EnumeratePhysicalDevices(); | ||
| 181 | const s32 device_index = Settings::values.vulkan_device.GetValue(); | ||
| 182 | if (device_index < 0 || device_index >= static_cast<s32>(devices.size())) { | ||
| 183 | LOG_ERROR(Render_Vulkan, "Invalid device index {}!", device_index); | ||
| 184 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | ||
| 185 | } | ||
| 186 | const vk::PhysicalDevice physical_device(devices[static_cast<size_t>(device_index)], dld); | ||
| 187 | device = std::make_unique<Device>(*instance, physical_device, *surface, dld); | ||
| 188 | } | ||
| 189 | |||
| 190 | void RendererVulkan::Report() const { | 160 | void RendererVulkan::Report() const { |
| 191 | const std::string vendor_name{device->GetVendorName()}; | 161 | const std::string vendor_name{device.GetVendorName()}; |
| 192 | const std::string model_name{device->GetModelName()}; | 162 | const std::string model_name{device.GetModelName()}; |
| 193 | const std::string driver_version = GetDriverVersion(*device); | 163 | const std::string driver_version = GetDriverVersion(device); |
| 194 | const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version); | 164 | const std::string driver_name = fmt::format("{} {}", vendor_name, driver_version); |
| 195 | 165 | ||
| 196 | const std::string api_version = GetReadableVersion(device->ApiVersion()); | 166 | const std::string api_version = GetReadableVersion(device.ApiVersion()); |
| 197 | 167 | ||
| 198 | const std::string extensions = BuildCommaSeparatedExtensions(device->GetAvailableExtensions()); | 168 | const std::string extensions = BuildCommaSeparatedExtensions(device.GetAvailableExtensions()); |
| 199 | 169 | ||
| 200 | LOG_INFO(Render_Vulkan, "Driver: {}", driver_name); | 170 | LOG_INFO(Render_Vulkan, "Driver: {}", driver_name); |
| 201 | LOG_INFO(Render_Vulkan, "Device: {}", model_name); | 171 | LOG_INFO(Render_Vulkan, "Device: {}", model_name); |
| @@ -209,21 +179,4 @@ void RendererVulkan::Report() const { | |||
| 209 | telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); | 179 | telemetry_session.AddField(field, "GPU_Vulkan_Extensions", extensions); |
| 210 | } | 180 | } |
| 211 | 181 | ||
| 212 | std::vector<std::string> RendererVulkan::EnumerateDevices() try { | ||
| 213 | vk::InstanceDispatch dld; | ||
| 214 | const Common::DynamicLibrary library = OpenLibrary(); | ||
| 215 | const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0); | ||
| 216 | const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); | ||
| 217 | std::vector<std::string> names; | ||
| 218 | names.reserve(physical_devices.size()); | ||
| 219 | for (const VkPhysicalDevice device : physical_devices) { | ||
| 220 | names.push_back(vk::PhysicalDevice(device, dld).GetProperties().deviceName); | ||
| 221 | } | ||
| 222 | return names; | ||
| 223 | |||
| 224 | } catch (const vk::Exception& exception) { | ||
| 225 | LOG_ERROR(Render_Vulkan, "Failed to enumerate devices with error: {}", exception.what()); | ||
| 226 | return {}; | ||
| 227 | } | ||
| 228 | |||
| 229 | } // namespace Vulkan | 182 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index daf55b9b4..1efaf3b77 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h | |||
| @@ -9,8 +9,14 @@ | |||
| 9 | #include <vector> | 9 | #include <vector> |
| 10 | 10 | ||
| 11 | #include "common/dynamic_library.h" | 11 | #include "common/dynamic_library.h" |
| 12 | |||
| 13 | #include "video_core/renderer_base.h" | 12 | #include "video_core/renderer_base.h" |
| 13 | #include "video_core/renderer_vulkan/vk_blit_screen.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_rasterizer.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 16 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | ||
| 17 | #include "video_core/renderer_vulkan/vk_swapchain.h" | ||
| 18 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 19 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | ||
| 14 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 20 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 15 | 21 | ||
| 16 | namespace Core { | 22 | namespace Core { |
| @@ -27,20 +33,6 @@ class GPU; | |||
| 27 | 33 | ||
| 28 | namespace Vulkan { | 34 | namespace Vulkan { |
| 29 | 35 | ||
| 30 | class Device; | ||
| 31 | class StateTracker; | ||
| 32 | class MemoryAllocator; | ||
| 33 | class VKBlitScreen; | ||
| 34 | class VKSwapchain; | ||
| 35 | class VKScheduler; | ||
| 36 | |||
| 37 | struct VKScreenInfo { | ||
| 38 | VkImageView image_view{}; | ||
| 39 | u32 width{}; | ||
| 40 | u32 height{}; | ||
| 41 | bool is_srgb{}; | ||
| 42 | }; | ||
| 43 | |||
| 44 | class RendererVulkan final : public VideoCore::RendererBase { | 36 | class RendererVulkan final : public VideoCore::RendererBase { |
| 45 | public: | 37 | public: |
| 46 | explicit RendererVulkan(Core::TelemetrySession& telemtry_session, | 38 | explicit RendererVulkan(Core::TelemetrySession& telemtry_session, |
| @@ -49,15 +41,13 @@ public: | |||
| 49 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); | 41 | std::unique_ptr<Core::Frontend::GraphicsContext> context_); |
| 50 | ~RendererVulkan() override; | 42 | ~RendererVulkan() override; |
| 51 | 43 | ||
| 52 | bool Init() override; | ||
| 53 | void ShutDown() override; | ||
| 54 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | 44 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; |
| 55 | 45 | ||
| 56 | static std::vector<std::string> EnumerateDevices(); | 46 | VideoCore::RasterizerInterface* ReadRasterizer() override { |
| 47 | return &rasterizer; | ||
| 48 | } | ||
| 57 | 49 | ||
| 58 | private: | 50 | private: |
| 59 | void InitializeDevice(); | ||
| 60 | |||
| 61 | void Report() const; | 51 | void Report() const; |
| 62 | 52 | ||
| 63 | Core::TelemetrySession& telemetry_session; | 53 | Core::TelemetrySession& telemetry_session; |
| @@ -74,12 +64,13 @@ private: | |||
| 74 | VKScreenInfo screen_info; | 64 | VKScreenInfo screen_info; |
| 75 | 65 | ||
| 76 | vk::DebugUtilsMessenger debug_callback; | 66 | vk::DebugUtilsMessenger debug_callback; |
| 77 | std::unique_ptr<Device> device; | 67 | Device device; |
| 78 | std::unique_ptr<MemoryAllocator> memory_allocator; | 68 | MemoryAllocator memory_allocator; |
| 79 | std::unique_ptr<StateTracker> state_tracker; | 69 | StateTracker state_tracker; |
| 80 | std::unique_ptr<VKScheduler> scheduler; | 70 | VKScheduler scheduler; |
| 81 | std::unique_ptr<VKSwapchain> swapchain; | 71 | VKSwapchain swapchain; |
| 82 | std::unique_ptr<VKBlitScreen> blit_screen; | 72 | VKBlitScreen blit_screen; |
| 73 | RasterizerVulkan rasterizer; | ||
| 83 | }; | 74 | }; |
| 84 | 75 | ||
| 85 | } // namespace Vulkan | 76 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 3e3b895e0..df8992528 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #include "video_core/gpu.h" | 18 | #include "video_core/gpu.h" |
| 19 | #include "video_core/host_shaders/vulkan_present_frag_spv.h" | 19 | #include "video_core/host_shaders/vulkan_present_frag_spv.h" |
| 20 | #include "video_core/host_shaders/vulkan_present_vert_spv.h" | 20 | #include "video_core/host_shaders/vulkan_present_vert_spv.h" |
| 21 | #include "video_core/rasterizer_interface.h" | ||
| 22 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 21 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| 23 | #include "video_core/renderer_vulkan/vk_blit_screen.h" | 22 | #include "video_core/renderer_vulkan/vk_blit_screen.h" |
| 24 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" | 23 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" |
| @@ -113,13 +112,12 @@ struct VKBlitScreen::BufferData { | |||
| 113 | }; | 112 | }; |
| 114 | 113 | ||
| 115 | VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_, | 114 | VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_, |
| 116 | Core::Frontend::EmuWindow& render_window_, | 115 | Core::Frontend::EmuWindow& render_window_, const Device& device_, |
| 117 | VideoCore::RasterizerInterface& rasterizer_, const Device& device_, | ||
| 118 | MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_, | 116 | MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_, |
| 119 | VKScheduler& scheduler_, const VKScreenInfo& screen_info_) | 117 | VKScheduler& scheduler_, const VKScreenInfo& screen_info_) |
| 120 | : cpu_memory{cpu_memory_}, render_window{render_window_}, rasterizer{rasterizer_}, | 118 | : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_}, |
| 121 | device{device_}, memory_allocator{memory_allocator_}, swapchain{swapchain_}, | 119 | memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_}, |
| 122 | scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { | 120 | image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { |
| 123 | resource_ticks.resize(image_count); | 121 | resource_ticks.resize(image_count); |
| 124 | 122 | ||
| 125 | CreateStaticResources(); | 123 | CreateStaticResources(); |
| @@ -159,7 +157,6 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, bool | |||
| 159 | const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; | 157 | const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; |
| 160 | const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); | 158 | const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); |
| 161 | const size_t size_bytes = GetSizeInBytes(framebuffer); | 159 | const size_t size_bytes = GetSizeInBytes(framebuffer); |
| 162 | rasterizer.FlushRegion(ToCacheAddr(host_ptr), size_bytes); | ||
| 163 | 160 | ||
| 164 | // TODO(Rodrigo): Read this from HLE | 161 | // TODO(Rodrigo): Read this from HLE |
| 165 | constexpr u32 block_height_log2 = 4; | 162 | constexpr u32 block_height_log2 = 4; |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h index b52576957..5e3177685 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.h +++ b/src/video_core/renderer_vulkan/vk_blit_screen.h | |||
| @@ -38,12 +38,18 @@ class RasterizerVulkan; | |||
| 38 | class VKScheduler; | 38 | class VKScheduler; |
| 39 | class VKSwapchain; | 39 | class VKSwapchain; |
| 40 | 40 | ||
| 41 | class VKBlitScreen final { | 41 | struct VKScreenInfo { |
| 42 | VkImageView image_view{}; | ||
| 43 | u32 width{}; | ||
| 44 | u32 height{}; | ||
| 45 | bool is_srgb{}; | ||
| 46 | }; | ||
| 47 | |||
| 48 | class VKBlitScreen { | ||
| 42 | public: | 49 | public: |
| 43 | explicit VKBlitScreen(Core::Memory::Memory& cpu_memory, | 50 | explicit VKBlitScreen(Core::Memory::Memory& cpu_memory, |
| 44 | Core::Frontend::EmuWindow& render_window, | 51 | Core::Frontend::EmuWindow& render_window, const Device& device, |
| 45 | VideoCore::RasterizerInterface& rasterizer, const Device& device, | 52 | MemoryAllocator& memory_manager, VKSwapchain& swapchain, |
| 46 | MemoryAllocator& memory_allocator, VKSwapchain& swapchain, | ||
| 47 | VKScheduler& scheduler, const VKScreenInfo& screen_info); | 53 | VKScheduler& scheduler, const VKScreenInfo& screen_info); |
| 48 | ~VKBlitScreen(); | 54 | ~VKBlitScreen(); |
| 49 | 55 | ||
| @@ -84,7 +90,6 @@ private: | |||
| 84 | 90 | ||
| 85 | Core::Memory::Memory& cpu_memory; | 91 | Core::Memory::Memory& cpu_memory; |
| 86 | Core::Frontend::EmuWindow& render_window; | 92 | Core::Frontend::EmuWindow& render_window; |
| 87 | VideoCore::RasterizerInterface& rasterizer; | ||
| 88 | const Device& device; | 93 | const Device& device; |
| 89 | MemoryAllocator& memory_allocator; | 94 | MemoryAllocator& memory_allocator; |
| 90 | VKSwapchain& swapchain; | 95 | VKSwapchain& swapchain; |
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 725a2a05d..0b63bd6c8 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -56,8 +56,11 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi | |||
| 56 | 56 | ||
| 57 | } // Anonymous namespace | 57 | } // Anonymous namespace |
| 58 | 58 | ||
| 59 | VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_) | 59 | VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_, |
| 60 | : surface{surface_}, device{device_}, scheduler{scheduler_} {} | 60 | u32 width, u32 height, bool srgb) |
| 61 | : surface{surface_}, device{device_}, scheduler{scheduler_} { | ||
| 62 | Create(width, height, srgb); | ||
| 63 | } | ||
| 61 | 64 | ||
| 62 | VKSwapchain::~VKSwapchain() = default; | 65 | VKSwapchain::~VKSwapchain() = default; |
| 63 | 66 | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 2eadd62b3..a728511e0 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h | |||
| @@ -20,7 +20,8 @@ class VKScheduler; | |||
| 20 | 20 | ||
| 21 | class VKSwapchain { | 21 | class VKSwapchain { |
| 22 | public: | 22 | public: |
| 23 | explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler); | 23 | explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler, |
| 24 | u32 width, u32 height, bool srgb); | ||
| 24 | ~VKSwapchain(); | 25 | ~VKSwapchain(); |
| 25 | 26 | ||
| 26 | /// Creates (or recreates) the swapchain with a given size. | 27 | /// Creates (or recreates) the swapchain with a given size. |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 53444e945..e1b38c6ac 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -38,19 +38,18 @@ namespace VideoCore { | |||
| 38 | 38 | ||
| 39 | 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) { |
| 40 | const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); | 40 | const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); |
| 41 | std::unique_ptr<Tegra::GPU> gpu = std::make_unique<Tegra::GPU>( | 41 | const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 42 | system, Settings::values.use_asynchronous_gpu_emulation.GetValue(), use_nvdec); | 42 | auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec); |
| 43 | |||
| 44 | auto context = emu_window.CreateSharedContext(); | 43 | auto context = emu_window.CreateSharedContext(); |
| 45 | const auto scope = context->Acquire(); | 44 | auto scope = context->Acquire(); |
| 46 | 45 | try { | |
| 47 | auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); | 46 | auto renderer = CreateRenderer(system, emu_window, *gpu, std::move(context)); |
| 48 | if (!renderer->Init()) { | 47 | gpu->BindRenderer(std::move(renderer)); |
| 48 | return gpu; | ||
| 49 | } catch (const std::runtime_error& exception) { | ||
| 50 | LOG_ERROR(HW_GPU, "Failed to initialize GPU: {}", exception.what()); | ||
| 49 | return nullptr; | 51 | return nullptr; |
| 50 | } | 52 | } |
| 51 | |||
| 52 | gpu->BindRenderer(std::move(renderer)); | ||
| 53 | return gpu; | ||
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { | 55 | u16 GetResolutionScaleFactor(const RendererBase& renderer) { |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 4b66dba7a..f1697b79a 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -23,7 +23,7 @@ enum class FormatType { Linear, Optimal, Buffer }; | |||
| 23 | const u32 GuestWarpSize = 32; | 23 | const u32 GuestWarpSize = 32; |
| 24 | 24 | ||
| 25 | /// Handles data specific to a physical device. | 25 | /// Handles data specific to a physical device. |
| 26 | class Device final { | 26 | class Device { |
| 27 | public: | 27 | public: |
| 28 | explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface, | 28 | explicit Device(VkInstance instance, vk::PhysicalDevice physical, VkSurfaceKHR surface, |
| 29 | const vk::InstanceDispatch& dld); | 29 | const vk::InstanceDispatch& dld); |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 9689de0cb..4d8f14357 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -344,6 +344,9 @@ public: | |||
| 344 | /// Construct an empty handle. | 344 | /// Construct an empty handle. |
| 345 | Handle() = default; | 345 | Handle() = default; |
| 346 | 346 | ||
| 347 | /// Construct an empty handle. | ||
| 348 | Handle(std::nullptr_t) {} | ||
| 349 | |||
| 347 | /// Copying Vulkan objects is not supported and will never be. | 350 | /// Copying Vulkan objects is not supported and will never be. |
| 348 | Handle(const Handle&) = delete; | 351 | Handle(const Handle&) = delete; |
| 349 | Handle& operator=(const Handle&) = delete; | 352 | Handle& operator=(const Handle&) = delete; |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index d9a3035cb..1c61d419d 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -64,7 +64,7 @@ void EmuThread::run() { | |||
| 64 | 64 | ||
| 65 | emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); | 65 | emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); |
| 66 | 66 | ||
| 67 | system.Renderer().Rasterizer().LoadDiskResources( | 67 | system.Renderer().ReadRasterizer()->LoadDiskResources( |
| 68 | system.CurrentProcess()->GetTitleID(), stop_run, | 68 | system.CurrentProcess()->GetTitleID(), stop_run, |
| 69 | [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { | 69 | [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { |
| 70 | emit LoadProgress(stage, value, total); | 70 | emit LoadProgress(stage, value, total); |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index b78a5dff0..b36d6a7c8 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -11,7 +11,8 @@ | |||
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/settings.h" | 12 | #include "core/settings.h" |
| 13 | #include "ui_configure_graphics.h" | 13 | #include "ui_configure_graphics.h" |
| 14 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 14 | #include "video_core/vulkan_common/vulkan_instance.h" |
| 15 | #include "video_core/vulkan_common/vulkan_library.h" | ||
| 15 | #include "yuzu/configuration/configuration_shared.h" | 16 | #include "yuzu/configuration/configuration_shared.h" |
| 16 | #include "yuzu/configuration/configure_graphics.h" | 17 | #include "yuzu/configuration/configure_graphics.h" |
| 17 | 18 | ||
| @@ -212,11 +213,23 @@ void ConfigureGraphics::UpdateDeviceComboBox() { | |||
| 212 | ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn()); | 213 | ui->device->setEnabled(enabled && !Core::System::GetInstance().IsPoweredOn()); |
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | void ConfigureGraphics::RetrieveVulkanDevices() { | 216 | void ConfigureGraphics::RetrieveVulkanDevices() try { |
| 217 | using namespace Vulkan; | ||
| 218 | |||
| 219 | vk::InstanceDispatch dld; | ||
| 220 | const Common::DynamicLibrary library = OpenLibrary(); | ||
| 221 | const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0); | ||
| 222 | const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); | ||
| 223 | |||
| 216 | vulkan_devices.clear(); | 224 | vulkan_devices.clear(); |
| 217 | for (const auto& name : Vulkan::RendererVulkan::EnumerateDevices()) { | 225 | vulkan_devices.reserve(physical_devices.size()); |
| 226 | for (const VkPhysicalDevice device : physical_devices) { | ||
| 227 | const char* const name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; | ||
| 218 | vulkan_devices.push_back(QString::fromStdString(name)); | 228 | vulkan_devices.push_back(QString::fromStdString(name)); |
| 219 | } | 229 | } |
| 230 | |||
| 231 | } catch (const Vulkan::vk::Exception& exception) { | ||
| 232 | LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); | ||
| 220 | } | 233 | } |
| 221 | 234 | ||
| 222 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { | 235 | Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 0e1f3bdb3..982c41785 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -215,7 +215,7 @@ int main(int argc, char** argv) { | |||
| 215 | // Core is loaded, start the GPU (makes the GPU contexts current to this thread) | 215 | // Core is loaded, start the GPU (makes the GPU contexts current to this thread) |
| 216 | system.GPU().Start(); | 216 | system.GPU().Start(); |
| 217 | 217 | ||
| 218 | system.Renderer().Rasterizer().LoadDiskResources( | 218 | system.Renderer().ReadRasterizer()->LoadDiskResources( |
| 219 | system.CurrentProcess()->GetTitleID(), false, | 219 | system.CurrentProcess()->GetTitleID(), false, |
| 220 | [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); | 220 | [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); |
| 221 | 221 | ||