mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 10:44:49 +01:00 
			
		
		
		
	Merge pull request #9344 from liamwhite/null
video_core: add null backend
This commit is contained in:
		
						commit
						f77cc6c412
					
				| @ -19,6 +19,7 @@ namespace Settings { | ||||
| enum class RendererBackend : u32 { | ||||
|     OpenGL = 0, | ||||
|     Vulkan = 1, | ||||
|     Null = 2, | ||||
| }; | ||||
| 
 | ||||
| enum class ShaderBackend : u32 { | ||||
| @ -411,7 +412,7 @@ struct Values { | ||||
| 
 | ||||
|     // Renderer
 | ||||
|     SwitchableSetting<RendererBackend, true> renderer_backend{ | ||||
|         RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"}; | ||||
|         RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"}; | ||||
|     Setting<bool> renderer_debug{false, "debug"}; | ||||
|     Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; | ||||
|     Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | ||||
|  | ||||
| @ -55,6 +55,8 @@ static const char* TranslateRenderer(Settings::RendererBackend backend) { | ||||
|         return "OpenGL"; | ||||
|     case Settings::RendererBackend::Vulkan: | ||||
|         return "Vulkan"; | ||||
|     case Settings::RendererBackend::Null: | ||||
|         return "Null"; | ||||
|     } | ||||
|     return "Unknown"; | ||||
| } | ||||
|  | ||||
| @ -92,6 +92,10 @@ add_library(video_core STATIC | ||||
|     rasterizer_interface.h | ||||
|     renderer_base.cpp | ||||
|     renderer_base.h | ||||
|     renderer_null/null_rasterizer.cpp | ||||
|     renderer_null/null_rasterizer.h | ||||
|     renderer_null/renderer_null.cpp | ||||
|     renderer_null/renderer_null.h | ||||
|     renderer_opengl/gl_buffer_cache.cpp | ||||
|     renderer_opengl/gl_buffer_cache.h | ||||
|     renderer_opengl/gl_compute_pipeline.cpp | ||||
|  | ||||
							
								
								
									
										90
									
								
								src/video_core/renderer_null/null_rasterizer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/video_core/renderer_null/null_rasterizer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "video_core/host1x/host1x.h" | ||||
| #include "video_core/memory_manager.h" | ||||
| #include "video_core/renderer_null/null_rasterizer.h" | ||||
| 
 | ||||
| namespace Null { | ||||
| 
 | ||||
| AccelerateDMA::AccelerateDMA() = default; | ||||
| 
 | ||||
| bool AccelerateDMA::BufferCopy(GPUVAddr start_address, GPUVAddr end_address, u64 amount) { | ||||
|     return true; | ||||
| } | ||||
| bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu) | ||||
|     : RasterizerAccelerated(cpu_memory_), m_gpu{gpu} {} | ||||
| RasterizerNull::~RasterizerNull() = default; | ||||
| 
 | ||||
| void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} | ||||
| void RasterizerNull::Clear(u32 layer_count) {} | ||||
| void RasterizerNull::DispatchCompute() {} | ||||
| void RasterizerNull::ResetCounter(VideoCore::QueryType type) {} | ||||
| void RasterizerNull::Query(GPUVAddr gpu_addr, VideoCore::QueryType type, | ||||
|                            std::optional<u64> timestamp) { | ||||
|     if (!gpu_memory) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     gpu_memory->Write(gpu_addr, u64{0}); | ||||
|     if (timestamp) { | ||||
|         gpu_memory->Write(gpu_addr + 8, *timestamp); | ||||
|     } | ||||
| } | ||||
| void RasterizerNull::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, | ||||
|                                                u32 size) {} | ||||
| void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {} | ||||
| void RasterizerNull::FlushAll() {} | ||||
| void RasterizerNull::FlushRegion(VAddr addr, u64 size) {} | ||||
| bool RasterizerNull::MustFlushRegion(VAddr addr, u64 size) { | ||||
|     return false; | ||||
| } | ||||
| void RasterizerNull::InvalidateRegion(VAddr addr, u64 size) {} | ||||
| void RasterizerNull::OnCPUWrite(VAddr addr, u64 size) {} | ||||
| void RasterizerNull::InvalidateGPUCache() {} | ||||
| void RasterizerNull::UnmapMemory(VAddr addr, u64 size) {} | ||||
| void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {} | ||||
| void RasterizerNull::SignalFence(std::function<void()>&& func) { | ||||
|     func(); | ||||
| } | ||||
| void RasterizerNull::SyncOperation(std::function<void()>&& func) { | ||||
|     func(); | ||||
| } | ||||
| void RasterizerNull::SignalSyncPoint(u32 value) { | ||||
|     auto& syncpoint_manager = m_gpu.Host1x().GetSyncpointManager(); | ||||
|     syncpoint_manager.IncrementGuest(value); | ||||
|     syncpoint_manager.IncrementHost(value); | ||||
| } | ||||
| void RasterizerNull::SignalReference() {} | ||||
| void RasterizerNull::ReleaseFences() {} | ||||
| void RasterizerNull::FlushAndInvalidateRegion(VAddr addr, u64 size) {} | ||||
| void RasterizerNull::WaitForIdle() {} | ||||
| void RasterizerNull::FragmentBarrier() {} | ||||
| void RasterizerNull::TiledCacheBarrier() {} | ||||
| void RasterizerNull::FlushCommands() {} | ||||
| void RasterizerNull::TickFrame() {} | ||||
| Tegra::Engines::AccelerateDMAInterface& RasterizerNull::AccessAccelerateDMA() { | ||||
|     return m_accelerate_dma; | ||||
| } | ||||
| bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | ||||
|                                            const Tegra::Engines::Fermi2D::Surface& dst, | ||||
|                                            const Tegra::Engines::Fermi2D::Config& copy_config) { | ||||
|     return true; | ||||
| } | ||||
| void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | ||||
|                                               std::span<const u8> memory) {} | ||||
| bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, | ||||
|                                        VAddr framebuffer_addr, u32 pixel_stride) { | ||||
|     return true; | ||||
| } | ||||
| void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | ||||
|                                        const VideoCore::DiskResourceLoadCallback& callback) {} | ||||
| void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {} | ||||
| void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) {} | ||||
| void RasterizerNull::ReleaseChannel(s32 channel_id) {} | ||||
| 
 | ||||
| } // namespace Null
 | ||||
							
								
								
									
										78
									
								
								src/video_core/renderer_null/null_rasterizer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/video_core/renderer_null/null_rasterizer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/control/channel_state_cache.h" | ||||
| #include "video_core/engines/maxwell_dma.h" | ||||
| #include "video_core/rasterizer_accelerated.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace Null { | ||||
| 
 | ||||
| class RasterizerNull; | ||||
| 
 | ||||
| class AccelerateDMA : public Tegra::Engines::AccelerateDMAInterface { | ||||
| public: | ||||
|     explicit AccelerateDMA(); | ||||
|     bool BufferCopy(GPUVAddr start_address, GPUVAddr end_address, u64 amount) override; | ||||
|     bool BufferClear(GPUVAddr src_address, u64 amount, u32 value) override; | ||||
| }; | ||||
| 
 | ||||
| class RasterizerNull final : public VideoCore::RasterizerAccelerated, | ||||
|                              protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | ||||
| public: | ||||
|     explicit RasterizerNull(Core::Memory::Memory& cpu_memory, Tegra::GPU& gpu); | ||||
|     ~RasterizerNull() override; | ||||
| 
 | ||||
|     void Draw(bool is_indexed, u32 instance_count) override; | ||||
|     void Clear(u32 layer_count) override; | ||||
|     void DispatchCompute() override; | ||||
|     void ResetCounter(VideoCore::QueryType type) override; | ||||
|     void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; | ||||
|     void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; | ||||
|     void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; | ||||
|     void FlushAll() override; | ||||
|     void FlushRegion(VAddr addr, u64 size) override; | ||||
|     bool MustFlushRegion(VAddr addr, u64 size) override; | ||||
|     void InvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void OnCPUWrite(VAddr addr, u64 size) override; | ||||
|     void InvalidateGPUCache() override; | ||||
|     void UnmapMemory(VAddr addr, u64 size) override; | ||||
|     void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | ||||
|     void SignalFence(std::function<void()>&& func) override; | ||||
|     void SyncOperation(std::function<void()>&& func) override; | ||||
|     void SignalSyncPoint(u32 value) override; | ||||
|     void SignalReference() override; | ||||
|     void ReleaseFences() override; | ||||
|     void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||||
|     void WaitForIdle() override; | ||||
|     void FragmentBarrier() override; | ||||
|     void TiledCacheBarrier() override; | ||||
|     void FlushCommands() override; | ||||
|     void TickFrame() override; | ||||
|     bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | ||||
|                                const Tegra::Engines::Fermi2D::Surface& dst, | ||||
|                                const Tegra::Engines::Fermi2D::Config& copy_config) override; | ||||
|     Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | ||||
|     void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | ||||
|                                   std::span<const u8> memory) override; | ||||
|     bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | ||||
|                            u32 pixel_stride) override; | ||||
|     void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | ||||
|                            const VideoCore::DiskResourceLoadCallback& callback) override; | ||||
|     void InitializeChannel(Tegra::Control::ChannelState& channel) override; | ||||
|     void BindChannel(Tegra::Control::ChannelState& channel) override; | ||||
|     void ReleaseChannel(s32 channel_id) override; | ||||
| 
 | ||||
| private: | ||||
|     Tegra::GPU& m_gpu; | ||||
|     AccelerateDMA m_accelerate_dma; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Null
 | ||||
							
								
								
									
										24
									
								
								src/video_core/renderer_null/renderer_null.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/video_core/renderer_null/renderer_null.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "video_core/renderer_null/renderer_null.h" | ||||
| 
 | ||||
| namespace Null { | ||||
| 
 | ||||
| RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | ||||
|                            Tegra::GPU& gpu, | ||||
|                            std::unique_ptr<Core::Frontend::GraphicsContext> context_) | ||||
|     : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(cpu_memory, gpu) {} | ||||
| 
 | ||||
| RendererNull::~RendererNull() = default; | ||||
| 
 | ||||
| void RendererNull::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||||
|     if (!framebuffer) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     m_gpu.RendererFrameEndNotify(); | ||||
|     render_window.OnFrameDisplayed(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Null
 | ||||
							
								
								
									
										36
									
								
								src/video_core/renderer_null/renderer_null.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/video_core/renderer_null/renderer_null.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/renderer_null/null_rasterizer.h" | ||||
| 
 | ||||
| namespace Null { | ||||
| 
 | ||||
| class RendererNull final : public VideoCore::RendererBase { | ||||
| public: | ||||
|     explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | ||||
|                           Tegra::GPU& gpu, | ||||
|                           std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||||
|     ~RendererNull() override; | ||||
| 
 | ||||
|     void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | ||||
| 
 | ||||
|     VideoCore::RasterizerInterface* ReadRasterizer() override { | ||||
|         return &m_rasterizer; | ||||
|     } | ||||
| 
 | ||||
|     [[nodiscard]] std::string GetDeviceVendor() const override { | ||||
|         return "NULL"; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Tegra::GPU& m_gpu; | ||||
|     RasterizerNull m_rasterizer; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Null
 | ||||
| @ -7,6 +7,7 @@ | ||||
| #include "common/settings.h" | ||||
| #include "core/core.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/renderer_null/renderer_null.h" | ||||
| #include "video_core/renderer_opengl/renderer_opengl.h" | ||||
| #include "video_core/renderer_vulkan/renderer_vulkan.h" | ||||
| #include "video_core/video_core.h" | ||||
| @ -26,6 +27,9 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer( | ||||
|     case Settings::RendererBackend::Vulkan: | ||||
|         return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, cpu_memory, | ||||
|                                                         gpu, std::move(context)); | ||||
|     case Settings::RendererBackend::Null: | ||||
|         return std::make_unique<Null::RendererNull>(emu_window, cpu_memory, gpu, | ||||
|                                                     std::move(context)); | ||||
|     default: | ||||
|         return nullptr; | ||||
|     } | ||||
|  | ||||
| @ -237,8 +237,7 @@ private: | ||||
|     GRenderWindow* render_window; | ||||
| }; | ||||
| 
 | ||||
| class OpenGLRenderWidget : public RenderWidget { | ||||
| public: | ||||
| struct OpenGLRenderWidget : public RenderWidget { | ||||
|     explicit OpenGLRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { | ||||
|         windowHandle()->setSurfaceType(QWindow::OpenGLSurface); | ||||
|     } | ||||
| @ -251,13 +250,16 @@ private: | ||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> context; | ||||
| }; | ||||
| 
 | ||||
| class VulkanRenderWidget : public RenderWidget { | ||||
| public: | ||||
| struct VulkanRenderWidget : public RenderWidget { | ||||
|     explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { | ||||
|         windowHandle()->setSurfaceType(QWindow::VulkanSurface); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| struct NullRenderWidget : public RenderWidget { | ||||
|     explicit NullRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {} | ||||
| }; | ||||
| 
 | ||||
| static Core::Frontend::WindowSystemType GetWindowSystemType() { | ||||
|     // Determine WSI type based on Qt platform.
 | ||||
|     QString platform_name = QGuiApplication::platformName(); | ||||
| @ -878,6 +880,9 @@ bool GRenderWindow::InitRenderTarget() { | ||||
|             return false; | ||||
|         } | ||||
|         break; | ||||
|     case Settings::RendererBackend::Null: | ||||
|         InitializeNull(); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     // Update the Window System information with the new render target
 | ||||
| @ -974,6 +979,11 @@ bool GRenderWindow::InitializeVulkan() { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void GRenderWindow::InitializeNull() { | ||||
|     child_widget = new NullRenderWidget(this); | ||||
|     main_context = std::make_unique<DummyContext>(); | ||||
| } | ||||
| 
 | ||||
| bool GRenderWindow::LoadOpenGL() { | ||||
|     auto context = CreateSharedContext(); | ||||
|     auto scope = context->Acquire(); | ||||
|  | ||||
| @ -219,6 +219,7 @@ private: | ||||
| 
 | ||||
|     bool InitializeOpenGL(); | ||||
|     bool InitializeVulkan(); | ||||
|     void InitializeNull(); | ||||
|     bool LoadOpenGL(); | ||||
|     QStringList GetUnsupportedGLExtensions() const; | ||||
| 
 | ||||
|  | ||||
| @ -260,6 +260,7 @@ void ConfigureGraphics::ApplyConfiguration() { | ||||
|             Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | ||||
|             switch (GetCurrentGraphicsBackend()) { | ||||
|             case Settings::RendererBackend::OpenGL: | ||||
|             case Settings::RendererBackend::Null: | ||||
|                 Settings::values.shader_backend.SetGlobal(false); | ||||
|                 Settings::values.vulkan_device.SetGlobal(true); | ||||
|                 Settings::values.shader_backend.SetValue(shader_backend); | ||||
| @ -348,6 +349,10 @@ void ConfigureGraphics::UpdateAPILayout() { | ||||
|         ui->device_widget->setVisible(true); | ||||
|         ui->backend_widget->setVisible(false); | ||||
|         break; | ||||
|     case Settings::RendererBackend::Null: | ||||
|         ui->device_widget->setVisible(false); | ||||
|         ui->backend_widget->setVisible(false); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -139,6 +139,11 @@ | ||||
|                   <string notr="true">Vulkan</string> | ||||
|                  </property> | ||||
|                 </item> | ||||
|                 <item> | ||||
|                  <property name="text"> | ||||
|                   <string>None</string> | ||||
|                  </property> | ||||
|                 </item> | ||||
|                </widget> | ||||
|               </item> | ||||
|              </layout> | ||||
|  | ||||
| @ -1012,29 +1012,11 @@ void GMainWindow::InitializeWidgets() { | ||||
|     renderer_status_button->setObjectName(QStringLiteral("RendererStatusBarButton")); | ||||
|     renderer_status_button->setCheckable(true); | ||||
|     renderer_status_button->setFocusPolicy(Qt::NoFocus); | ||||
|     connect(renderer_status_button, &QPushButton::toggled, [this](bool checked) { | ||||
|         renderer_status_button->setText(checked ? tr("VULKAN") : tr("OPENGL")); | ||||
|     }); | ||||
|     renderer_status_button->toggle(); | ||||
| 
 | ||||
|     connect(renderer_status_button, &QPushButton::clicked, this, &GMainWindow::OnToggleGraphicsAPI); | ||||
|     UpdateAPIText(); | ||||
|     renderer_status_button->setCheckable(true); | ||||
|     renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == | ||||
|                                        Settings::RendererBackend::Vulkan); | ||||
|     connect(renderer_status_button, &QPushButton::clicked, [this] { | ||||
|         if (emulation_running) { | ||||
|             return; | ||||
|         } | ||||
|         if (renderer_status_button->isChecked()) { | ||||
|             Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); | ||||
|         } else { | ||||
|             Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); | ||||
|             if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { | ||||
|                 Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); | ||||
|                 UpdateFilterText(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         system->ApplySettings(); | ||||
|     }); | ||||
|     statusBar()->insertPermanentWidget(0, renderer_status_button); | ||||
| 
 | ||||
|     statusBar()->setVisible(true); | ||||
| @ -3259,6 +3241,18 @@ void GMainWindow::OnToggleAdaptingFilter() { | ||||
|     UpdateFilterText(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnToggleGraphicsAPI() { | ||||
|     auto api = Settings::values.renderer_backend.GetValue(); | ||||
|     if (api == Settings::RendererBackend::OpenGL) { | ||||
|         api = Settings::RendererBackend::Vulkan; | ||||
|     } else { | ||||
|         api = Settings::RendererBackend::OpenGL; | ||||
|     } | ||||
|     Settings::values.renderer_backend.SetValue(api); | ||||
|     renderer_status_button->setChecked(api == Settings::RendererBackend::Vulkan); | ||||
|     UpdateAPIText(); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::OnConfigurePerGame() { | ||||
|     const u64 title_id = system->GetCurrentProcessProgramID(); | ||||
|     OpenPerGameConfiguration(title_id, current_game_path.toStdString()); | ||||
| @ -3579,6 +3573,21 @@ void GMainWindow::UpdateDockedButton() { | ||||
|     dock_status_button->setText(is_docked ? tr("DOCKED") : tr("HANDHELD")); | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::UpdateAPIText() { | ||||
|     const auto api = Settings::values.renderer_backend.GetValue(); | ||||
|     switch (api) { | ||||
|     case Settings::RendererBackend::OpenGL: | ||||
|         renderer_status_button->setText(tr("OPENGL")); | ||||
|         break; | ||||
|     case Settings::RendererBackend::Vulkan: | ||||
|         renderer_status_button->setText(tr("VULKAN")); | ||||
|         break; | ||||
|     case Settings::RendererBackend::Null: | ||||
|         renderer_status_button->setText(tr("NULL")); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void GMainWindow::UpdateFilterText() { | ||||
|     const auto filter = Settings::values.scaling_filter.GetValue(); | ||||
|     switch (filter) { | ||||
| @ -3624,6 +3633,7 @@ void GMainWindow::UpdateAAText() { | ||||
| void GMainWindow::UpdateStatusButtons() { | ||||
|     renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == | ||||
|                                        Settings::RendererBackend::Vulkan); | ||||
|     UpdateAPIText(); | ||||
|     UpdateGPUAccuracyButton(); | ||||
|     UpdateDockedButton(); | ||||
|     UpdateFilterText(); | ||||
|  | ||||
| @ -307,6 +307,7 @@ private slots: | ||||
|     void OnTasStartStop(); | ||||
|     void OnTasRecord(); | ||||
|     void OnTasReset(); | ||||
|     void OnToggleGraphicsAPI(); | ||||
|     void OnToggleDockedMode(); | ||||
|     void OnToggleGpuAccuracy(); | ||||
|     void OnToggleAdaptingFilter(); | ||||
| @ -347,6 +348,7 @@ private: | ||||
|     void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, | ||||
|                            std::string_view gpu_vendor = {}); | ||||
|     void UpdateDockedButton(); | ||||
|     void UpdateAPIText(); | ||||
|     void UpdateFilterText(); | ||||
|     void UpdateAAText(); | ||||
|     void UpdateStatusBar(); | ||||
|  | ||||
| @ -22,6 +22,8 @@ add_executable(yuzu-cmd | ||||
|     emu_window/emu_window_sdl2.h | ||||
|     emu_window/emu_window_sdl2_gl.cpp | ||||
|     emu_window/emu_window_sdl2_gl.h | ||||
|     emu_window/emu_window_sdl2_null.cpp | ||||
|     emu_window/emu_window_sdl2_null.h | ||||
|     emu_window/emu_window_sdl2_vk.cpp | ||||
|     emu_window/emu_window_sdl2_vk.h | ||||
|     precompiled_headers.h | ||||
|  | ||||
| @ -89,3 +89,5 @@ protected: | ||||
|     /// yuzu core instance
 | ||||
|     Core::System& system; | ||||
| }; | ||||
| 
 | ||||
| class DummyContext : public Core::Frontend::GraphicsContext {}; | ||||
|  | ||||
							
								
								
									
										51
									
								
								src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| #include <fmt/format.h> | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "common/scm_rev.h" | ||||
| #include "video_core/renderer_null/renderer_null.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" | ||||
| 
 | ||||
| #ifdef YUZU_USE_EXTERNAL_SDL2 | ||||
| // Include this before SDL.h to prevent the external from including a dummy
 | ||||
| #define USING_GENERATED_CONFIG_H | ||||
| #include <SDL_config.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <SDL.h> | ||||
| 
 | ||||
| EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, | ||||
|                                          Core::System& system_, bool fullscreen) | ||||
|     : EmuWindow_SDL2{input_subsystem_, system_} { | ||||
|     const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, | ||||
|                                                  Common::g_scm_branch, Common::g_scm_desc); | ||||
|     render_window = | ||||
|         SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | ||||
|                          Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, | ||||
|                          SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); | ||||
| 
 | ||||
|     SetWindowIcon(); | ||||
| 
 | ||||
|     if (fullscreen) { | ||||
|         Fullscreen(); | ||||
|         ShowCursor(false); | ||||
|     } | ||||
| 
 | ||||
|     OnResize(); | ||||
|     OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); | ||||
|     SDL_PumpEvents(); | ||||
|     LOG_INFO(Frontend, "yuzu Version: {} | {}-{} (Null)", Common::g_build_name, | ||||
|              Common::g_scm_branch, Common::g_scm_desc); | ||||
| } | ||||
| 
 | ||||
| EmuWindow_SDL2_Null::~EmuWindow_SDL2_Null() = default; | ||||
| 
 | ||||
| std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_Null::CreateSharedContext() const { | ||||
|     return std::make_unique<DummyContext>(); | ||||
| } | ||||
							
								
								
									
										26
									
								
								src/yuzu_cmd/emu_window/emu_window_sdl2_null.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/yuzu_cmd/emu_window/emu_window_sdl2_null.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "core/frontend/emu_window.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
| namespace InputCommon { | ||||
| class InputSubsystem; | ||||
| } | ||||
| 
 | ||||
| class EmuWindow_SDL2_Null final : public EmuWindow_SDL2 { | ||||
| public: | ||||
|     explicit EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, | ||||
|                                  Core::System& system, bool fullscreen); | ||||
|     ~EmuWindow_SDL2_Null() override; | ||||
| 
 | ||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | ||||
| }; | ||||
| @ -24,5 +24,3 @@ public: | ||||
| 
 | ||||
|     std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | ||||
| }; | ||||
| 
 | ||||
| class DummyContext : public Core::Frontend::GraphicsContext {}; | ||||
|  | ||||
| @ -34,6 +34,7 @@ | ||||
| #include "yuzu_cmd/config.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" | ||||
| #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| @ -317,6 +318,9 @@ int main(int argc, char** argv) { | ||||
|     case Settings::RendererBackend::Vulkan: | ||||
|         emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, system, fullscreen); | ||||
|         break; | ||||
|     case Settings::RendererBackend::Null: | ||||
|         emu_window = std::make_unique<EmuWindow_SDL2_Null>(&input_subsystem, system, fullscreen); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user