diff options
| -rw-r--r-- | src/core/core.cpp | 9 | ||||
| -rw-r--r-- | src/core/core.h | 22 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 6 | ||||
| -rw-r--r-- | src/core/memory.cpp | 24 | ||||
| -rw-r--r-- | src/core/settings.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 8 | ||||
| -rw-r--r-- | src/video_core/gpu.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/gpu.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_base.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_base.h | 14 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.h | 2 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/video_core.h | 20 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu_cmd/yuzu.cpp | 2 | 
19 files changed, 110 insertions, 80 deletions
| diff --git a/src/core/core.cpp b/src/core/core.cpp index e51e66550..e01c45cdd 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,6 +18,7 @@  #include "core/loader/loader.h"  #include "core/settings.h"  #include "file_sys/vfs_real.h" +#include "video_core/renderer_base.h"  #include "video_core/video_core.h"  namespace Core { @@ -178,7 +179,6 @@ System::ResultStatus System::Init(EmuWindow& emu_window) {          cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index);      } -    gpu_core = std::make_unique<Tegra::GPU>();      telemetry_session = std::make_unique<Core::TelemetrySession>();      service_manager = std::make_shared<Service::SM::ServiceManager>(); @@ -186,10 +186,13 @@ System::ResultStatus System::Init(EmuWindow& emu_window) {      Service::Init(service_manager);      GDBStub::Init(); -    if (!VideoCore::Init(emu_window)) { +    renderer = VideoCore::CreateRenderer(emu_window); +    if (!renderer->Init()) {          return ResultStatus::ErrorVideoCore;      } +    gpu_core = std::make_unique<Tegra::GPU>(renderer->Rasterizer()); +      // Create threads for CPU cores 1-3, and build thread_to_cpu map      // CPU core 0 is run on the main thread      thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0]; @@ -221,7 +224,7 @@ void System::Shutdown() {                           perf_results.frametime * 1000.0);      // Shutdown emulation session -    VideoCore::Shutdown(); +    renderer.reset();      GDBStub::Shutdown();      Service::Shutdown();      Kernel::Shutdown(); diff --git a/src/core/core.h b/src/core/core.h index 4c9967559..a3be88aa8 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -27,6 +27,10 @@ namespace Service::SM {  class ServiceManager;  } +namespace VideoCore { +class RendererBase; +} +  namespace Core {  class System { @@ -129,11 +133,26 @@ public:      /// Gets a CPU interface to the CPU core with the specified index      Cpu& CpuCore(size_t core_index); -    /// Gets the GPU interface +    /// Gets a mutable reference to the GPU interface      Tegra::GPU& GPU() {          return *gpu_core;      } +    /// Gets an immutable reference to the GPU interface. +    const Tegra::GPU& GPU() const { +        return *gpu_core; +    } + +    /// Gets a mutable reference to the renderer. +    VideoCore::RendererBase& Renderer() { +        return *renderer; +    } + +    /// Gets an immutable reference to the renderer. +    const VideoCore::RendererBase& Renderer() const { +        return *renderer; +    } +      /// Gets the scheduler for the CPU core that is currently running      Kernel::Scheduler& CurrentScheduler() {          return *CurrentCpuCore().Scheduler(); @@ -197,6 +216,7 @@ private:      /// AppLoader used to load the current executing application      std::unique_ptr<Loader::AppLoader> app_loader; +    std::unique_ptr<VideoCore::RendererBase> renderer;      std::unique_ptr<Tegra::GPU> gpu_core;      std::shared_ptr<Tegra::DebugContext> debug_context;      Kernel::SharedPtr<Kernel::Process> current_process; diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index ed69a4325..2b74e6a33 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -30,9 +30,9 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3          addr,      offset,   width, height, stride, static_cast<PixelFormat>(format),          transform, crop_rect}; -    Core::System::GetInstance().perf_stats.EndGameFrame(); - -    VideoCore::g_renderer->SwapBuffers(framebuffer); +    auto& instance = Core::System::GetInstance(); +    instance.perf_stats.EndGameFrame(); +    instance.Renderer().SwapBuffers(framebuffer);  }  } // namespace Service::Nvidia::Devices diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 57b128b40..4b601781f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -150,15 +150,16 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou      LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset); -    auto& gpu = Core::System::GetInstance().GPU(); - -    auto itr = buffer_mappings.find(params.offset); - +    const auto itr = buffer_mappings.find(params.offset);      ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping"); +    auto& system_instance = Core::System::GetInstance(); +      // Remove this memory region from the rasterizer cache. -    VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(params.offset, itr->second.size); +    system_instance.Renderer().Rasterizer().FlushAndInvalidateRegion(params.offset, +                                                                     itr->second.size); +    auto& gpu = system_instance.GPU();      params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);      buffer_mappings.erase(itr->second.offset); diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 5344441e1..0bf51062c 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -127,9 +127,11 @@ void NVFlinger::Compose() {          MicroProfileFlip();          if (buffer == boost::none) { +            auto& system_instance = Core::System::GetInstance(); +              // There was no queued buffer to draw, render previous frame -            Core::System::GetInstance().perf_stats.EndGameFrame(); -            VideoCore::g_renderer->SwapBuffers({}); +            system_instance.perf_stats.EndGameFrame(); +            system_instance.Renderer().SwapBuffers({});              continue;          } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 4b3bb7b31..1133bcbaf 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -326,43 +326,45 @@ void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached)  }  void RasterizerFlushVirtualRegion(VAddr start, u64 size, FlushMode mode) { +    auto& system_instance = Core::System::GetInstance(); +      // Since pages are unmapped on shutdown after video core is shutdown, the renderer may be      // null here -    if (VideoCore::g_renderer == nullptr) { +    if (!system_instance.IsPoweredOn()) {          return;      }      VAddr end = start + size; -    auto CheckRegion = [&](VAddr region_start, VAddr region_end) { +    const auto CheckRegion = [&](VAddr region_start, VAddr region_end) {          if (start >= region_end || end <= region_start) {              // No overlap with region              return;          } -        VAddr overlap_start = std::max(start, region_start); -        VAddr overlap_end = std::min(end, region_end); +        const VAddr overlap_start = std::max(start, region_start); +        const VAddr overlap_end = std::min(end, region_end); -        std::vector<Tegra::GPUVAddr> gpu_addresses = -            Core::System::GetInstance().GPU().memory_manager->CpuToGpuAddress(overlap_start); +        const std::vector<Tegra::GPUVAddr> gpu_addresses = +            system_instance.GPU().memory_manager->CpuToGpuAddress(overlap_start);          if (gpu_addresses.empty()) {              return;          } -        u64 overlap_size = overlap_end - overlap_start; +        const u64 overlap_size = overlap_end - overlap_start;          for (const auto& gpu_address : gpu_addresses) { -            auto* rasterizer = VideoCore::g_renderer->Rasterizer(); +            auto& rasterizer = system_instance.Renderer().Rasterizer();              switch (mode) {              case FlushMode::Flush: -                rasterizer->FlushRegion(gpu_address, overlap_size); +                rasterizer.FlushRegion(gpu_address, overlap_size);                  break;              case FlushMode::Invalidate: -                rasterizer->InvalidateRegion(gpu_address, overlap_size); +                rasterizer.InvalidateRegion(gpu_address, overlap_size);                  break;              case FlushMode::FlushAndInvalidate: -                rasterizer->FlushAndInvalidateRegion(gpu_address, overlap_size); +                rasterizer.FlushAndInvalidateRegion(gpu_address, overlap_size);                  break;              }          } diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 79e0b347b..a4623223d 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -2,6 +2,7 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include "core/core.h"  #include "core/gdbstub/gdbstub.h"  #include "core/hle/service/hid/hid.h"  #include "core/settings.h" @@ -19,8 +20,9 @@ void Apply() {      VideoCore::g_toggle_framelimit_enabled = values.toggle_framelimit; -    if (VideoCore::g_renderer) { -        VideoCore::g_renderer->UpdateCurrentFramebufferLayout(); +    auto& system_instance = Core::System::GetInstance(); +    if (system_instance.IsPoweredOn()) { +        system_instance.Renderer().UpdateCurrentFramebufferLayout();      }      Service::HID::ReloadInputDevices(); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 0e205ed72..a235b543e 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -19,8 +19,8 @@ namespace Engines {  /// First register id that is actually a Macro call.  constexpr u32 MacroRegistersStart = 0xE00; -Maxwell3D::Maxwell3D(MemoryManager& memory_manager) -    : memory_manager(memory_manager), macro_interpreter(*this) {} +Maxwell3D::Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager) +    : memory_manager(memory_manager), rasterizer{rasterizer}, macro_interpreter(*this) {}  void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {      auto macro_code = uploaded_macros.find(method); @@ -130,7 +130,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {          break;      } -    VideoCore::g_renderer->Rasterizer()->NotifyMaxwellRegisterChanged(method); +    rasterizer.NotifyMaxwellRegisterChanged(method);      if (debug_context) {          debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr); @@ -218,7 +218,7 @@ void Maxwell3D::DrawArrays() {      }      const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count}; -    VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(is_indexed); +    rasterizer.AccelerateDrawBatch(is_indexed);      // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if      // the game is trying to draw indexed or direct mode. This needs to be verified on HW still - @@ -393,7 +393,7 @@ void Maxwell3D::ProcessClearBuffers() {             regs.clear_buffers.R == regs.clear_buffers.B &&             regs.clear_buffers.R == regs.clear_buffers.A); -    VideoCore::g_renderer->Rasterizer()->Clear(); +    rasterizer.Clear();  }  } // namespace Engines diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 3c32f1067..4d0ff96a5 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -17,6 +17,10 @@  #include "video_core/memory_manager.h"  #include "video_core/textures/texture.h" +namespace VideoCore { +class RasterizerInterface; +} +  namespace Tegra::Engines {  #define MAXWELL3D_REG_INDEX(field_name)                                                            \ @@ -24,7 +28,7 @@ namespace Tegra::Engines {  class Maxwell3D final {  public: -    explicit Maxwell3D(MemoryManager& memory_manager); +    explicit Maxwell3D(VideoCore::RasterizerInterface& rasterizer, MemoryManager& memory_manager);      ~Maxwell3D() = default;      /// Register structure of the Maxwell3D engine. @@ -818,6 +822,8 @@ public:      Texture::FullTextureInfo GetStageTexture(Regs::ShaderStage stage, size_t offset) const;  private: +    VideoCore::RasterizerInterface& rasterizer; +      std::unordered_map<u32, std::vector<u32>> uploaded_macros;      /// Macro method that is currently being executed / being fed parameters. diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 141e20444..b2a83ce0b 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -7,12 +7,13 @@  #include "video_core/engines/maxwell_compute.h"  #include "video_core/engines/maxwell_dma.h"  #include "video_core/gpu.h" +#include "video_core/rasterizer_interface.h"  namespace Tegra { -GPU::GPU() { +GPU::GPU(VideoCore::RasterizerInterface& rasterizer) {      memory_manager = std::make_unique<MemoryManager>(); -    maxwell_3d = std::make_unique<Engines::Maxwell3D>(*memory_manager); +    maxwell_3d = std::make_unique<Engines::Maxwell3D>(rasterizer, *memory_manager);      fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager);      maxwell_compute = std::make_unique<Engines::MaxwellCompute>();      maxwell_dma = std::make_unique<Engines::MaxwellDMA>(*memory_manager); diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 08aa75503..440505c9d 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -11,6 +11,10 @@  #include "core/hle/service/nvflinger/buffer_queue.h"  #include "video_core/memory_manager.h" +namespace VideoCore { +class RasterizerInterface; +} +  namespace Tegra {  enum class RenderTargetFormat : u32 { @@ -98,7 +102,7 @@ enum class EngineID {  class GPU final {  public: -    GPU(); +    explicit GPU(VideoCore::RasterizerInterface& rasterizer);      ~GPU();      /// Processes a command list stored at the specified address in GPU memory. diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index dbe3edf09..3ca350243 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp @@ -7,6 +7,8 @@  #include "video_core/renderer_base.h"  #include "video_core/renderer_opengl/gl_rasterizer.h" +namespace VideoCore { +  RendererBase::RendererBase(EmuWindow& window) : render_window{window} {}  RendererBase::~RendererBase() = default; @@ -21,3 +23,5 @@ void RendererBase::RefreshRasterizerSetting() {          rasterizer = std::make_unique<RasterizerOpenGL>(render_window);      }  } + +} // namespace VideoCore diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 1cb161b7f..235de23a1 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -13,6 +13,8 @@  class EmuWindow; +namespace VideoCore { +  class RendererBase : NonCopyable {  public:      /// Used to reference a framebuffer @@ -44,15 +46,21 @@ public:          return m_current_frame;      } -    VideoCore::RasterizerInterface* Rasterizer() const { -        return rasterizer.get(); +    RasterizerInterface& Rasterizer() { +        return *rasterizer; +    } + +    const RasterizerInterface& Rasterizer() const { +        return *rasterizer;      }      void RefreshRasterizerSetting();  protected:      EmuWindow& render_window; ///< Reference to the render window handle. -    std::unique_ptr<VideoCore::RasterizerInterface> rasterizer; +    std::unique_ptr<RasterizerInterface> rasterizer;      f32 m_current_fps = 0.0f; ///< Current framerate, should be set by the renderer      int m_current_frame = 0;  ///< Current frame, should be set by the renderer  }; + +} // namespace VideoCore diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 74383c7cf..bf9131193 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -103,7 +103,7 @@ ScopeAcquireGLContext::~ScopeAcquireGLContext() {      }  } -RendererOpenGL::RendererOpenGL(EmuWindow& window) : RendererBase{window} {} +RendererOpenGL::RendererOpenGL(EmuWindow& window) : VideoCore::RendererBase{window} {}  RendererOpenGL::~RendererOpenGL() = default;  /// Swap buffers (render frame) @@ -160,8 +160,8 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf      // only allows rows to have a memory alignement of 4.      ASSERT(framebuffer.stride % 4 == 0); -    if (!Rasterizer()->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride, -                                         screen_info)) { +    if (!rasterizer->AccelerateDisplay(framebuffer, framebuffer_addr, framebuffer.stride, +                                       screen_info)) {          // Reset the screen info's display texture to its own permanent texture          screen_info.display_texture = screen_info.texture.resource.handle; diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index ab7de41c8..428afa3b7 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -41,7 +41,7 @@ private:      EmuWindow& emu_window;  }; -class RendererOpenGL : public RendererBase { +class RendererOpenGL : public VideoCore::RendererBase {  public:      explicit RendererOpenGL(EmuWindow& window);      ~RendererOpenGL() override; diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 06b13e681..5085ef96b 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp @@ -3,37 +3,16 @@  // Refer to the license.txt file included.  #include <memory> -#include "common/logging/log.h"  #include "video_core/renderer_base.h"  #include "video_core/renderer_opengl/renderer_opengl.h"  #include "video_core/video_core.h" -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Video Core namespace -  namespace VideoCore { -std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin -  std::atomic<bool> g_toggle_framelimit_enabled; -/// Initialize the video core -bool Init(EmuWindow& emu_window) { -    g_renderer = std::make_unique<RendererOpenGL>(emu_window); -    if (g_renderer->Init()) { -        LOG_DEBUG(Render, "initialized OK"); -    } else { -        LOG_CRITICAL(Render, "initialization failed !"); -        return false; -    } -    return true; -} - -/// Shutdown the video core -void Shutdown() { -    g_renderer.reset(); - -    LOG_DEBUG(Render, "shutdown OK"); +std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window) { +    return std::make_unique<RendererOpenGL>(emu_window);  }  } // namespace VideoCore diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h index 519b757f5..7c01c0b8d 100644 --- a/src/video_core/video_core.h +++ b/src/video_core/video_core.h @@ -8,25 +8,23 @@  #include <memory>  class EmuWindow; -class RendererBase; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Video Core namespace  namespace VideoCore { -enum class Renderer { Software, OpenGL }; +class RendererBase; -extern std::unique_ptr<RendererBase> g_renderer; ///< Renderer plugin +enum class Renderer { Software, OpenGL };  // TODO: Wrap these in a user settings struct along with any other graphics settings (often set from  // qt ui)  extern std::atomic<bool> g_toggle_framelimit_enabled; -/// Initialize the video core -bool Init(EmuWindow& emu_window); - -/// Shutdown the video core -void Shutdown(); +/** + * Creates a renderer instance. + * + * @note The returned renderer instance is simply allocated. Its Init() + *       function still needs to be called to fully complete its setup. + */ +std::unique_ptr<RendererBase> CreateRenderer(EmuWindow& emu_window);  } // namespace VideoCore diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index eac41553a..e28679cd1 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -477,7 +477,7 @@ bool GMainWindow::LoadROM(const QString& filename) {          case Core::System::ResultStatus::ErrorVideoCore:              QMessageBox::critical( -                this, tr("An error occured in the video core."), +                this, tr("An error occurred initializing the video core."),                  tr("yuzu has encountered an error while running the video core, please see the "                     "log for more details."                     "For more information on accessing the log, please see the following page: " @@ -491,7 +491,7 @@ bool GMainWindow::LoadROM(const QString& filename) {          default:              QMessageBox::critical(                  this, tr("Error while loading ROM!"), -                tr("An unknown error occured. Please see the log for more details.")); +                tr("An unknown error occurred. Please see the log for more details."));              break;          }          return false; diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index b23213cf6..d637dbd0c 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -193,7 +193,7 @@ int main(int argc, char** argv) {          LOG_CRITICAL(Frontend, "Failed to determine system mode!");          return -1;      case Core::System::ResultStatus::ErrorVideoCore: -        LOG_CRITICAL(Frontend, "VideoCore not initialized"); +        LOG_CRITICAL(Frontend, "Failed to initialize VideoCore!");          return -1;      case Core::System::ResultStatus::Success:          break; // Expected case | 
