Răsfoiți Sursa

NVDRV: Refactor Host1x

Fernando Sahmkow 4 ani în urmă
părinte
comite
2931101e6f
33 a modificat fișierele cu 201 adăugiri și 173 ștergeri
  1. 1 1
      src/core/core.cpp
  2. 4 4
      src/core/hle/service/nvdrv/core/container.cpp
  3. 7 3
      src/core/hle/service/nvdrv/core/container.h
  4. 14 19
      src/core/hle/service/nvdrv/core/nvmap.cpp
  5. 14 4
      src/core/hle/service/nvdrv/core/nvmap.h
  6. 3 3
      src/core/hle/service/nvdrv/core/syncpoint_manager.cpp
  7. 8 4
      src/core/hle/service/nvdrv/core/syncpoint_manager.h
  8. 11 26
      src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
  9. 1 1
      src/core/hle/service/nvdrv/nvdrv.cpp
  10. 2 0
      src/video_core/CMakeLists.txt
  11. 6 6
      src/video_core/cdma_pusher.cpp
  12. 3 4
      src/video_core/cdma_pusher.h
  13. 2 25
      src/video_core/gpu.cpp
  14. 0 6
      src/video_core/gpu.h
  15. 5 5
      src/video_core/host1x/codecs/codec.cpp
  16. 6 3
      src/video_core/host1x/codecs/codec.h
  17. 7 6
      src/video_core/host1x/codecs/h264.cpp
  18. 7 3
      src/video_core/host1x/codecs/h264.h
  19. 4 4
      src/video_core/host1x/codecs/vp8.cpp
  20. 7 3
      src/video_core/host1x/codecs/vp8.h
  21. 6 6
      src/video_core/host1x/codecs/vp9.cpp
  22. 7 3
      src/video_core/host1x/codecs/vp9.h
  23. 0 1
      src/video_core/host1x/codecs/vp9_types.h
  24. 2 3
      src/video_core/host1x/control.cpp
  25. 3 3
      src/video_core/host1x/control.h
  26. 18 0
      src/video_core/host1x/host1x.cpp
  27. 26 1
      src/video_core/host1x/host1x.h
  28. 3 2
      src/video_core/host1x/nvdec.cpp
  29. 4 3
      src/video_core/host1x/nvdec.h
  30. 2 3
      src/video_core/host1x/sync_manager.cpp
  31. 4 4
      src/video_core/host1x/sync_manager.h
  32. 11 11
      src/video_core/host1x/vic.cpp
  33. 3 3
      src/video_core/host1x/vic.h

+ 1 - 1
src/core/core.cpp

@@ -216,7 +216,7 @@ struct System::Impl {
 
         telemetry_session = std::make_unique<Core::TelemetrySession>();
 
-        host1x_core = std::make_unique<Tegra::Host1x::Host1x>();
+        host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
         gpu_core = VideoCore::CreateGPU(emu_window, system);
         if (!gpu_core) {
             return SystemResultStatus::ErrorVideoCore;

+ 4 - 4
src/core/hle/service/nvdrv/core/container.cpp

@@ -6,18 +6,18 @@
 #include "core/hle/service/nvdrv/core/container.h"
 #include "core/hle/service/nvdrv/core/nvmap.h"
 #include "core/hle/service/nvdrv/core/syncpoint_manager.h"
-#include "video_core/gpu.h"
+#include "video_core/host1x/host1x.h"
 
 namespace Service::Nvidia::NvCore {
 
 struct ContainerImpl {
-    ContainerImpl(Tegra::GPU& gpu_) : file{}, manager{gpu_} {}
+    ContainerImpl(Tegra::Host1x::Host1x& host1x_) : file{host1x_}, manager{host1x_} {}
     NvMap file;
     SyncpointManager manager;
 };
 
-Container::Container(Tegra::GPU& gpu_) {
-    impl = std::make_unique<ContainerImpl>(gpu_);
+Container::Container(Tegra::Host1x::Host1x& host1x_) {
+    impl = std::make_unique<ContainerImpl>(host1x_);
 }
 
 Container::~Container() = default;

+ 7 - 3
src/core/hle/service/nvdrv/core/container.h

@@ -8,8 +8,12 @@
 #include <memory>
 
 namespace Tegra {
-class GPU;
-}
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
+} // namespace Tegra
 
 namespace Service::Nvidia::NvCore {
 
@@ -20,7 +24,7 @@ struct ContainerImpl;
 
 class Container {
 public:
-    Container(Tegra::GPU& gpu_);
+    Container(Tegra::Host1x::Host1x& host1x);
     ~Container();
 
     NvMap& GetNvMapFile();

+ 14 - 19
src/core/hle/service/nvdrv/core/nvmap.cpp

@@ -7,6 +7,7 @@
 #include "common/logging/log.h"
 #include "core/hle/service/nvdrv/core/nvmap.h"
 #include "core/memory.h"
+#include "video_core/host1x/host1x.h"
 
 using Core::Memory::YUZU_PAGESIZE;
 
@@ -61,7 +62,7 @@ NvResult NvMap::Handle::Duplicate(bool internal_session) {
     return NvResult::Success;
 }
 
-NvMap::NvMap() = default;
+NvMap::NvMap(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {}
 
 void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) {
     std::scoped_lock lock(handles_lock);
@@ -77,12 +78,11 @@ void NvMap::UnmapHandle(Handle& handle_description) {
     }
 
     // Free and unmap the handle from the SMMU
-    /*
-    state.soc->smmu.Unmap(handle_description.pin_virt_address,
-    static_cast<u32>(handle_description.aligned_size));
-    smmuAllocator.Free(handle_description.pin_virt_address,
-    static_cast<u32>(handle_description.aligned_size)); handle_description.pin_virt_address = 0;
-    */
+    host1x.MemoryManager().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address),
+                                 handle_description.aligned_size);
+    host1x.Allocator().Free(handle_description.pin_virt_address,
+                            static_cast<u32>(handle_description.aligned_size));
+    handle_description.pin_virt_address = 0;
 }
 
 bool NvMap::TryRemoveHandle(const Handle& handle_description) {
@@ -131,12 +131,9 @@ VAddr NvMap::GetHandleAddress(Handle::Id handle) {
 }
 
 u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
-    UNIMPLEMENTED_MSG("pinning");
-    return 0;
-    /*
     auto handle_description{GetHandle(handle)};
-    if (!handle_description)
-        [[unlikely]] return 0;
+    if (!handle_description) [[unlikely]]
+        return 0;
 
     std::scoped_lock lock(handle_description->mutex);
     if (!handle_description->pins) {
@@ -157,8 +154,10 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
 
         // If not then allocate some space and map it
         u32 address{};
+        auto& smmu_allocator = host1x.Allocator();
+        auto& smmu_memory_manager = host1x.MemoryManager();
         while (!(address =
-    smmuAllocator.Allocate(static_cast<u32>(handle_description->aligned_size)))) {
+                     smmu_allocator.Allocate(static_cast<u32>(handle_description->aligned_size)))) {
             // Free handles until the allocation succeeds
             std::scoped_lock queueLock(unmap_queue_lock);
             if (auto freeHandleDesc{unmap_queue.front()}) {
@@ -172,19 +171,16 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
             }
         }
 
-        state.soc->smmu.Map(address, handle_description->GetPointer(),
-                            static_cast<u32>(handle_description->aligned_size));
+        smmu_memory_manager.Map(static_cast<GPUVAddr>(address), handle_description->address,
+                                handle_description->aligned_size);
         handle_description->pin_virt_address = address;
     }
 
     handle_description->pins++;
     return handle_description->pin_virt_address;
-    */
 }
 
 void NvMap::UnpinHandle(Handle::Id handle) {
-    UNIMPLEMENTED_MSG("Unpinning");
-    /*
     auto handle_description{GetHandle(handle)};
     if (!handle_description)
         return;
@@ -199,7 +195,6 @@ void NvMap::UnpinHandle(Handle::Id handle) {
         unmap_queue.push_back(handle_description);
         handle_description->unmap_queue_entry = std::prev(unmap_queue.end());
     }
-    */
 }
 
 std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {

+ 14 - 4
src/core/hle/service/nvdrv/core/nvmap.h

@@ -15,6 +15,14 @@
 #include "common/common_types.h"
 #include "core/hle/service/nvdrv/nvdata.h"
 
+namespace Tegra {
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
+} // namespace Tegra
+
 namespace Service::Nvidia::NvCore {
 /**
  * @brief The nvmap core class holds the global state for nvmap and provides methods to manage
@@ -90,15 +98,17 @@ public:
     };
 
 private:
-    std::list<std::shared_ptr<Handle>> unmap_queue;
-    std::mutex unmap_queue_lock; //!< Protects access to `unmap_queue`
+    std::list<std::shared_ptr<Handle>> unmap_queue{};
+    std::mutex unmap_queue_lock{}; //!< Protects access to `unmap_queue`
 
-    std::unordered_map<Handle::Id, std::shared_ptr<Handle>> handles; //!< Main owning map of handles
+    std::unordered_map<Handle::Id, std::shared_ptr<Handle>>
+        handles{};           //!< Main owning map of handles
     std::mutex handles_lock; //!< Protects access to `handles`
 
     static constexpr u32 HandleIdIncrement{
         4}; //!< Each new handle ID is an increment of 4 from the previous
     std::atomic<u32> next_handle_id{HandleIdIncrement};
+    Tegra::Host1x::Host1x& host1x;
 
     void AddHandle(std::shared_ptr<Handle> handle);
 
@@ -125,7 +135,7 @@ public:
         bool was_uncached; //!< If the handle was allocated as uncached
     };
 
-    NvMap();
+    NvMap(Tegra::Host1x::Host1x& host1x);
 
     /**
      * @brief Creates an unallocated handle of the given size

+ 3 - 3
src/core/hle/service/nvdrv/core/syncpoint_manager.cpp

@@ -3,16 +3,16 @@
 
 #include "common/assert.h"
 #include "core/hle/service/nvdrv/core/syncpoint_manager.h"
-#include "video_core/gpu.h"
+#include "video_core/host1x/host1x.h"
 
 namespace Service::Nvidia::NvCore {
 
-SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {}
+SyncpointManager::SyncpointManager(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {}
 
 SyncpointManager::~SyncpointManager() = default;
 
 u32 SyncpointManager::RefreshSyncpoint(u32 syncpoint_id) {
-    syncpoints[syncpoint_id].min = gpu.GetSyncpointValue(syncpoint_id);
+    syncpoints[syncpoint_id].min = host1x.GetSyncpointManager().GetHostSyncpointValue(syncpoint_id);
     return GetSyncpointMin(syncpoint_id);
 }
 

+ 8 - 4
src/core/hle/service/nvdrv/core/syncpoint_manager.h

@@ -10,14 +10,18 @@
 #include "core/hle/service/nvdrv/nvdata.h"
 
 namespace Tegra {
-class GPU;
-}
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
+} // namespace Tegra
 
 namespace Service::Nvidia::NvCore {
 
 class SyncpointManager final {
 public:
-    explicit SyncpointManager(Tegra::GPU& gpu_);
+    explicit SyncpointManager(Tegra::Host1x::Host1x& host1x);
     ~SyncpointManager();
 
     /**
@@ -78,7 +82,7 @@ private:
 
     std::array<Syncpoint, MaxSyncPoints> syncpoints{};
 
-    Tegra::GPU& gpu;
+    Tegra::Host1x::Host1x& host1x;
 };
 
 } // namespace Service::Nvidia::NvCore

+ 11 - 26
src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp

@@ -13,6 +13,7 @@
 #include "core/hle/service/nvdrv/core/syncpoint_manager.h"
 #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h"
 #include "core/memory.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/memory_manager.h"
 #include "video_core/renderer_base.h"
 
@@ -140,29 +141,8 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
 
     SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
 
-    auto& gpu = system.GPU();
-
     for (auto& cmd_buffer : cmd_buffer_handles) {
-        auto object{nvmap.GetHandle(cmd_buffer.map_handle)};
-        if (!object) {
-            LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
-            std::memcpy(output.data(), &params, output.size());
-            return NvResult::InvalidState;
-        }
-        if (object->dma_map_addr == 0) {
-            // NVDEC and VIC memory is in the 32-bit address space
-            // MapAllocate32 will attempt to map a lower 32-bit value in the shared gpu memory space
-            const GPUVAddr low_addr =
-                gpu.MemoryManager().MapAllocate32(object->address, object->size);
-            object->dma_map_addr = static_cast<u32>(low_addr);
-            // Ensure that the dma_map_addr is indeed in the lower 32-bit address space.
-            ASSERT(object->dma_map_addr == low_addr);
-        }
-        if (!object->dma_map_addr) {
-            LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size);
-        } else {
-            cmd_buffer.map_address = static_cast<u32_le>(object->dma_map_addr);
-        }
+        cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle);
     }
     std::memcpy(output.data(), &params, sizeof(IoctlMapBuffer));
     std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(),
@@ -172,11 +152,16 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
 }
 
 NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
-    // This is intntionally stubbed.
-    // Skip unmapping buffers here, as to not break the continuity of the VP9 reference frame
-    // addresses, and risk invalidating data before the async GPU thread is done with it
+    IoctlMapBuffer params{};
+    std::memcpy(&params, input.data(), sizeof(IoctlMapBuffer));
+    std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
+
+    SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
+    for (auto& cmd_buffer : cmd_buffer_handles) {
+        nvmap.UnpinHandle(cmd_buffer.map_handle);
+    }
+
     std::memset(output.data(), 0, output.size());
-    LOG_DEBUG(Service_NVDRV, "(STUBBED) called");
     return NvResult::Success;
 }
 

+ 1 - 1
src/core/hle/service/nvdrv/nvdrv.cpp

@@ -71,7 +71,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
 }
 
 Module::Module(Core::System& system)
-    : service_context{system, "nvdrv"}, events_interface{*this}, container{system.GPU()} {
+    : service_context{system, "nvdrv"}, events_interface{*this}, container{system.Host1x()} {
     builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) {
         std::shared_ptr<Devices::nvdevice> device =
             std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);

+ 2 - 0
src/video_core/CMakeLists.txt

@@ -56,6 +56,8 @@ add_library(video_core STATIC
     host1x/codecs/vp9_types.h
     host1x/control.cpp
     host1x/control.h
+    host1x/host1x.cpp
+    host1x/host1x.h
     host1x/nvdec.cpp
     host1x/nvdec.h
     host1x/nvdec_common.h

+ 6 - 6
src/video_core/cdma_pusher.cpp

@@ -4,8 +4,8 @@
 #include <bit>
 #include "video_core/cdma_pusher.h"
 #include "video_core/engines/maxwell_3d.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/control.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/host1x/nvdec.h"
 #include "video_core/host1x/nvdec_common.h"
 #include "video_core/host1x/sync_manager.h"
@@ -13,11 +13,11 @@
 #include "video_core/memory_manager.h"
 
 namespace Tegra {
-CDmaPusher::CDmaPusher(GPU& gpu_)
-    : gpu{gpu_}, nvdec_processor(std::make_shared<Host1x::Nvdec>(gpu)),
-      vic_processor(std::make_unique<Host1x::Vic>(gpu, nvdec_processor)),
-      host1x_processor(std::make_unique<Host1x::Control>(gpu)),
-      sync_manager(std::make_unique<Host1x::SyncptIncrManager>(gpu)) {}
+CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_)
+    : host1x{host1x_}, nvdec_processor(std::make_shared<Host1x::Nvdec>(host1x)),
+      vic_processor(std::make_unique<Host1x::Vic>(host1x, nvdec_processor)),
+      host1x_processor(std::make_unique<Host1x::Control>(host1x)),
+      sync_manager(std::make_unique<Host1x::SyncptIncrManager>(host1x)) {}
 
 CDmaPusher::~CDmaPusher() = default;
 

+ 3 - 4
src/video_core/cdma_pusher.h

@@ -12,10 +12,9 @@
 
 namespace Tegra {
 
-class GPU;
-
 namespace Host1x {
 class Control;
+class Host1x;
 class Nvdec;
 class SyncptIncrManager;
 class Vic;
@@ -91,7 +90,7 @@ enum class ThiMethod : u32 {
 
 class CDmaPusher {
 public:
-    explicit CDmaPusher(GPU& gpu_);
+    explicit CDmaPusher(Host1x::Host1x& host1x);
     ~CDmaPusher();
 
     /// Process the command entry
@@ -104,7 +103,7 @@ private:
     /// Write arguments value to the ThiRegisters member at the specified offset
     void ThiStateWrite(ThiRegisters& state, u32 offset, u32 argument);
 
-    GPU& gpu;
+    Host1x::Host1x& host1x;
     std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
     std::unique_ptr<Tegra::Host1x::Vic> vic_processor;
     std::unique_ptr<Tegra::Host1x::Control> host1x_processor;

+ 2 - 25
src/video_core/gpu.cpp

@@ -83,19 +83,11 @@ struct GPU::Impl {
         UNIMPLEMENTED();
     }
 
-    void CreateHost1xChannel() {
-        if (host1x_channel) {
-            return;
-        }
-        host1x_channel = CreateChannel(0);
-        host1x_channel->memory_manager = std::make_shared<Tegra::MemoryManager>(system);
-        InitChannel(*host1x_channel);
-    }
-
     /// Binds a renderer to the GPU.
     void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
         renderer = std::move(renderer_);
         rasterizer = renderer->ReadRasterizer();
+        host1x.MemoryManager().BindRasterizer(rasterizer);
     }
 
     /// Flush all current written commands into the host GPU for execution.
@@ -173,12 +165,6 @@ struct GPU::Impl {
         return *current_channel->kepler_compute;
     }
 
-    /// Returns a reference to the GPU memory manager.
-    [[nodiscard]] Tegra::MemoryManager& MemoryManager() {
-        CreateHost1xChannel();
-        return *host1x_channel->memory_manager;
-    }
-
     /// Returns a reference to the GPU DMA pusher.
     [[nodiscard]] Tegra::DmaPusher& DmaPusher() {
         ASSERT(current_channel);
@@ -299,7 +285,7 @@ struct GPU::Impl {
         }
 
         if (!cdma_pushers.contains(id)) {
-            cdma_pushers.insert_or_assign(id, std::make_unique<Tegra::CDmaPusher>(gpu));
+            cdma_pushers.insert_or_assign(id, std::make_unique<Tegra::CDmaPusher>(host1x));
         }
 
         // SubmitCommandBuffer would make the nvdec operations async, this is not currently working
@@ -389,7 +375,6 @@ struct GPU::Impl {
     VideoCore::RasterizerInterface* rasterizer = nullptr;
     const bool use_nvdec;
 
-    std::shared_ptr<Control::ChannelState> host1x_channel;
     s32 new_channel_id{1};
     /// Shader build notifier
     std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
@@ -510,14 +495,6 @@ const Engines::KeplerCompute& GPU::KeplerCompute() const {
     return impl->KeplerCompute();
 }
 
-Tegra::MemoryManager& GPU::MemoryManager() {
-    return impl->MemoryManager();
-}
-
-const Tegra::MemoryManager& GPU::MemoryManager() const {
-    return impl->MemoryManager();
-}
-
 Tegra::DmaPusher& GPU::DmaPusher() {
     return impl->DmaPusher();
 }

+ 0 - 6
src/video_core/gpu.h

@@ -153,12 +153,6 @@ public:
     /// Returns a reference to the KeplerCompute GPU engine.
     [[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const;
 
-    /// Returns a reference to the GPU memory manager.
-    [[nodiscard]] Tegra::MemoryManager& MemoryManager();
-
-    /// Returns a const reference to the GPU memory manager.
-    [[nodiscard]] const Tegra::MemoryManager& MemoryManager() const;
-
     /// Returns a reference to the GPU DMA pusher.
     [[nodiscard]] Tegra::DmaPusher& DmaPusher();
 

+ 5 - 5
src/video_core/host1x/codecs/codec.cpp

@@ -6,11 +6,11 @@
 #include <vector>
 #include "common/assert.h"
 #include "common/settings.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/codecs/codec.h"
 #include "video_core/host1x/codecs/h264.h"
 #include "video_core/host1x/codecs/vp8.h"
 #include "video_core/host1x/codecs/vp9.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/memory_manager.h"
 
 extern "C" {
@@ -73,10 +73,10 @@ void AVFrameDeleter(AVFrame* ptr) {
     av_frame_free(&ptr);
 }
 
-Codec::Codec(GPU& gpu_, const Host1x::NvdecCommon::NvdecRegisters& regs)
-    : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)),
-      vp8_decoder(std::make_unique<Decoder::VP8>(gpu)),
-      vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {}
+Codec::Codec(Host1x::Host1x& host1x_, const Host1x::NvdecCommon::NvdecRegisters& regs)
+    : host1x(host1x_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(host1x)),
+      vp8_decoder(std::make_unique<Decoder::VP8>(host1x)),
+      vp9_decoder(std::make_unique<Decoder::VP9>(host1x)) {}
 
 Codec::~Codec() {
     if (!initialized) {

+ 6 - 3
src/video_core/host1x/codecs/codec.h

@@ -21,7 +21,6 @@ extern "C" {
 }
 
 namespace Tegra {
-class GPU;
 
 void AVFrameDeleter(AVFrame* ptr);
 using AVFramePtr = std::unique_ptr<AVFrame, decltype(&AVFrameDeleter)>;
@@ -32,9 +31,13 @@ class VP8;
 class VP9;
 } // namespace Decoder
 
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
 class Codec {
 public:
-    explicit Codec(GPU& gpu, const Host1x::NvdecCommon::NvdecRegisters& regs);
+    explicit Codec(Host1x::Host1x& host1x, const Host1x::NvdecCommon::NvdecRegisters& regs);
     ~Codec();
 
     /// Initialize the codec, returning success or failure
@@ -69,7 +72,7 @@ private:
     AVCodecContext* av_codec_ctx{nullptr};
     AVBufferRef* av_gpu_decoder{nullptr};
 
-    GPU& gpu;
+    Host1x::Host1x& host1x;
     const Host1x::NvdecCommon::NvdecRegisters& state;
     std::unique_ptr<Decoder::H264> h264_decoder;
     std::unique_ptr<Decoder::VP8> vp8_decoder;

+ 7 - 6
src/video_core/host1x/codecs/h264.cpp

@@ -5,8 +5,8 @@
 #include <bit>
 
 #include "common/settings.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/codecs/h264.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/memory_manager.h"
 
 namespace Tegra::Decoder {
@@ -24,19 +24,20 @@ constexpr std::array<u8, 16> zig_zag_scan{
 };
 } // Anonymous namespace
 
-H264::H264(GPU& gpu_) : gpu(gpu_) {}
+H264::H264(Host1x::Host1x& host1x_) : host1x{host1x_} {}
 
 H264::~H264() = default;
 
 const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state,
                                           bool is_first_frame) {
     H264DecoderContext context;
-    gpu.MemoryManager().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext));
+    host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context,
+                                     sizeof(H264DecoderContext));
 
     const s64 frame_number = context.h264_parameter_set.frame_number.Value();
     if (!is_first_frame && frame_number != 0) {
         frame.resize(context.stream_len);
-        gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size());
+        host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size());
         return frame;
     }
 
@@ -155,8 +156,8 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist
     frame.resize(encoded_header.size() + context.stream_len);
     std::memcpy(frame.data(), encoded_header.data(), encoded_header.size());
 
-    gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset,
-                                  frame.data() + encoded_header.size(), context.stream_len);
+    host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset,
+                                     frame.data() + encoded_header.size(), context.stream_len);
 
     return frame;
 }

+ 7 - 3
src/video_core/host1x/codecs/h264.h

@@ -11,7 +11,11 @@
 #include "video_core/host1x/nvdec_common.h"
 
 namespace Tegra {
-class GPU;
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
 namespace Decoder {
 
 class H264BitWriter {
@@ -55,7 +59,7 @@ private:
 
 class H264 {
 public:
-    explicit H264(GPU& gpu);
+    explicit H264(Host1x::Host1x& host1x);
     ~H264();
 
     /// Compose the H264 frame for FFmpeg decoding
@@ -64,7 +68,7 @@ public:
 
 private:
     std::vector<u8> frame;
-    GPU& gpu;
+    Host1x::Host1x& host1x;
 
     struct H264ParameterSet {
         s32 log2_max_pic_order_cnt_lsb_minus4; ///< 0x00

+ 4 - 4
src/video_core/host1x/codecs/vp8.cpp

@@ -3,18 +3,18 @@
 
 #include <vector>
 
-#include "video_core/gpu.h"
 #include "video_core/host1x/codecs/vp8.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/memory_manager.h"
 
 namespace Tegra::Decoder {
-VP8::VP8(GPU& gpu_) : gpu(gpu_) {}
+VP8::VP8(Host1x::Host1x& host1x_) : host1x{host1x_} {}
 
 VP8::~VP8() = default;
 
 const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
     VP8PictureInfo info;
-    gpu.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo));
+    host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo));
 
     const bool is_key_frame = info.key_frame == 1u;
     const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size);
@@ -45,7 +45,7 @@ const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegiste
         frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f));
     }
     const u64 bitstream_offset = state.frame_bitstream_offset;
-    gpu.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size);
+    host1x.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size);
 
     return frame;
 }

+ 7 - 3
src/video_core/host1x/codecs/vp8.h

@@ -11,12 +11,16 @@
 #include "video_core/host1x/nvdec_common.h"
 
 namespace Tegra {
-class GPU;
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
 namespace Decoder {
 
 class VP8 {
 public:
-    explicit VP8(GPU& gpu);
+    explicit VP8(Host1x::Host1x& host1x);
     ~VP8();
 
     /// Compose the VP8 frame for FFmpeg decoding
@@ -25,7 +29,7 @@ public:
 
 private:
     std::vector<u8> frame;
-    GPU& gpu;
+    Host1x::Host1x& host1x;
 
     struct VP8PictureInfo {
         INSERT_PADDING_WORDS_NOINIT(14);

+ 6 - 6
src/video_core/host1x/codecs/vp9.cpp

@@ -4,8 +4,8 @@
 #include <algorithm> // for std::copy
 #include <numeric>
 #include "common/assert.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/codecs/vp9.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/memory_manager.h"
 
 namespace Tegra::Decoder {
@@ -236,7 +236,7 @@ constexpr std::array<u8, 254> map_lut{
 }
 } // Anonymous namespace
 
-VP9::VP9(GPU& gpu_) : gpu{gpu_} {}
+VP9::VP9(Host1x::Host1x& host1x_) : host1x{host1x_} {}
 
 VP9::~VP9() = default;
 
@@ -357,7 +357,7 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
 
 Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) {
     PictureInfo picture_info;
-    gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
+    host1x.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
     Vp9PictureInfo vp9_info = picture_info.Convert();
 
     InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy);
@@ -372,17 +372,17 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters&
 
 void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) {
     EntropyProbs entropy;
-    gpu.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs));
+    host1x.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs));
     entropy.Convert(dst);
 }
 
 Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
     Vp9FrameContainer current_frame{};
     {
-        gpu.SyncGuestHost();
+        // gpu.SyncGuestHost(); epic, why?
         current_frame.info = GetVp9PictureInfo(state);
         current_frame.bit_stream.resize(current_frame.info.bitstream_size);
-        gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(),
+        host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(),
                                       current_frame.info.bitstream_size);
     }
     if (!next_frame.bit_stream.empty()) {

+ 7 - 3
src/video_core/host1x/codecs/vp9.h

@@ -12,7 +12,11 @@
 #include "video_core/host1x/nvdec_common.h"
 
 namespace Tegra {
-class GPU;
+
+namespace Host1x {
+class Host1x;
+} // namespace Host1x
+
 namespace Decoder {
 
 /// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the
@@ -106,7 +110,7 @@ private:
 
 class VP9 {
 public:
-    explicit VP9(GPU& gpu_);
+    explicit VP9(Host1x::Host1x& host1x);
     ~VP9();
 
     VP9(const VP9&) = delete;
@@ -176,7 +180,7 @@ private:
     [[nodiscard]] std::vector<u8> ComposeCompressedHeader();
     [[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader();
 
-    GPU& gpu;
+    Host1x::Host1x& host1x;
     std::vector<u8> frame;
 
     std::array<s8, 4> loop_filter_ref_deltas{};

+ 0 - 1
src/video_core/host1x/codecs/vp9_types.h

@@ -9,7 +9,6 @@
 #include "common/common_types.h"
 
 namespace Tegra {
-class GPU;
 
 namespace Decoder {
 struct Vp9FrameDimensions {

+ 2 - 3
src/video_core/host1x/control.cpp

@@ -3,13 +3,12 @@
 // Refer to the license.txt file included.
 
 #include "common/assert.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/control.h"
 #include "video_core/host1x/host1x.h"
 
 namespace Tegra::Host1x {
 
-Control::Control(GPU& gpu_) : gpu(gpu_) {}
+Control::Control(Host1x& host1x_) : host1x(host1x_) {}
 
 Control::~Control() = default;
 
@@ -29,7 +28,7 @@ void Control::ProcessMethod(Method method, u32 argument) {
 }
 
 void Control::Execute(u32 data) {
-    gpu.Host1x().GetSyncpointManager().WaitHost(data, syncpoint_value);
+    host1x.GetSyncpointManager().WaitHost(data, syncpoint_value);
 }
 
 } // namespace Tegra::Host1x

+ 3 - 3
src/video_core/host1x/control.h

@@ -8,10 +8,10 @@
 #include "common/common_types.h"
 
 namespace Tegra {
-class GPU;
 
 namespace Host1x {
 
+class Host1x;
 class Nvdec;
 
 class Control {
@@ -22,7 +22,7 @@ public:
         WaitSyncpt32 = 0x50,
     };
 
-    explicit Control(GPU& gpu);
+    explicit Control(Host1x& host1x);
     ~Control();
 
     /// Writes the method into the state, Invoke Execute() if encountered
@@ -33,7 +33,7 @@ private:
     void Execute(u32 data);
 
     u32 syncpoint_value{};
-    GPU& gpu;
+    Host1x& host1x;
 };
 
 } // namespace Host1x

+ 18 - 0
src/video_core/host1x/host1x.cpp

@@ -0,0 +1,18 @@
+// Copyright 2022 yuzu Emulator Project
+// Licensed under GPLv3 or any later version
+// Refer to the license.txt file included.
+
+#include "core/core.h"
+#include "video_core/host1x/host1x.h"
+
+namespace Tegra {
+
+namespace Host1x {
+
+Host1x::Host1x(Core::System& system_)
+    : system{system_}, syncpoint_manager{}, memory_manager{system, 32, 12},
+      allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {}
+
+} // namespace Host1x
+
+} // namespace Tegra

+ 26 - 1
src/video_core/host1x/host1x.h

@@ -6,7 +6,13 @@
 
 #include "common/common_types.h"
 
+#include "common/address_space.h"
 #include "video_core/host1x/syncpoint_manager.h"
+#include "video_core/memory_manager.h"
+
+namespace Core {
+class System;
+} // namespace Core
 
 namespace Tegra {
 
@@ -14,7 +20,7 @@ namespace Host1x {
 
 class Host1x {
 public:
-    Host1x() : syncpoint_manager{} {}
+    Host1x(Core::System& system);
 
     SyncpointManager& GetSyncpointManager() {
         return syncpoint_manager;
@@ -24,8 +30,27 @@ public:
         return syncpoint_manager;
     }
 
+    Tegra::MemoryManager& MemoryManager() {
+        return memory_manager;
+    }
+
+    const Tegra::MemoryManager& MemoryManager() const {
+        return memory_manager;
+    }
+
+    Common::FlatAllocator<u32, 0, 32>& Allocator() {
+        return *allocator;
+    }
+
+    const Common::FlatAllocator<u32, 0, 32>& Allocator() const {
+        return *allocator;
+    }
+
 private:
+    Core::System& system;
     SyncpointManager syncpoint_manager;
+    Tegra::MemoryManager memory_manager;
+    std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator;
 };
 
 } // namespace Host1x

+ 3 - 2
src/video_core/host1x/nvdec.cpp

@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "common/assert.h"
-#include "video_core/gpu.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/host1x/nvdec.h"
 
 namespace Tegra::Host1x {
@@ -10,7 +10,8 @@ namespace Tegra::Host1x {
 #define NVDEC_REG_INDEX(field_name)                                                                \
     (offsetof(NvdecCommon::NvdecRegisters, field_name) / sizeof(u64))
 
-Nvdec::Nvdec(GPU& gpu_) : gpu(gpu_), state{}, codec(std::make_unique<Codec>(gpu, state)) {}
+Nvdec::Nvdec(Host1x& host1x_)
+    : host1x(host1x_), state{}, codec(std::make_unique<Codec>(host1x, state)) {}
 
 Nvdec::~Nvdec() = default;
 

+ 4 - 3
src/video_core/host1x/nvdec.h

@@ -9,13 +9,14 @@
 #include "video_core/host1x/codecs/codec.h"
 
 namespace Tegra {
-class GPU;
 
 namespace Host1x {
 
+class Host1x;
+
 class Nvdec {
 public:
-    explicit Nvdec(GPU& gpu);
+    explicit Nvdec(Host1x& host1x);
     ~Nvdec();
 
     /// Writes the method into the state, Invoke Execute() if encountered
@@ -28,7 +29,7 @@ private:
     /// Invoke codec to decode a frame
     void Execute();
 
-    GPU& gpu;
+    Host1x& host1x;
     NvdecCommon::NvdecRegisters state;
     std::unique_ptr<Codec> codec;
 };

+ 2 - 3
src/video_core/host1x/sync_manager.cpp

@@ -3,14 +3,13 @@
 
 #include <algorithm>
 #include "sync_manager.h"
-#include "video_core/gpu.h"
 #include "video_core/host1x/host1x.h"
 #include "video_core/host1x/syncpoint_manager.h"
 
 namespace Tegra {
 namespace Host1x {
 
-SyncptIncrManager::SyncptIncrManager(GPU& gpu_) : gpu(gpu_) {}
+SyncptIncrManager::SyncptIncrManager(Host1x& host1x_) : host1x(host1x_) {}
 SyncptIncrManager::~SyncptIncrManager() = default;
 
 void SyncptIncrManager::Increment(u32 id) {
@@ -40,7 +39,7 @@ void SyncptIncrManager::IncrementAllDone() {
         if (!increments[done_count].complete) {
             break;
         }
-        auto& syncpoint_manager = gpu.Host1x().GetSyncpointManager();
+        auto& syncpoint_manager = host1x.GetSyncpointManager();
         syncpoint_manager.IncrementGuest(increments[done_count].syncpt_id);
         syncpoint_manager.IncrementHost(increments[done_count].syncpt_id);
     }

+ 4 - 4
src/video_core/host1x/sync_manager.h

@@ -9,10 +9,10 @@
 
 namespace Tegra {
 
-class GPU;
-
 namespace Host1x {
 
+class Host1x;
+
 struct SyncptIncr {
     u32 id;
     u32 class_id;
@@ -25,7 +25,7 @@ struct SyncptIncr {
 
 class SyncptIncrManager {
 public:
-    explicit SyncptIncrManager(GPU& gpu);
+    explicit SyncptIncrManager(Host1x& host1x);
     ~SyncptIncrManager();
 
     /// Add syncpoint id and increment all
@@ -45,7 +45,7 @@ private:
     std::mutex increment_lock;
     u32 current_id{};
 
-    GPU& gpu;
+    Host1x& host1x;
 };
 
 } // namespace Host1x

+ 11 - 11
src/video_core/host1x/vic.cpp

@@ -19,7 +19,7 @@ extern "C" {
 #include "common/logging/log.h"
 
 #include "video_core/engines/maxwell_3d.h"
-#include "video_core/gpu.h"
+#include "video_core/host1x/host1x.h"
 #include "video_core/host1x/nvdec.h"
 #include "video_core/host1x/vic.h"
 #include "video_core/memory_manager.h"
@@ -49,8 +49,8 @@ union VicConfig {
     BitField<46, 14, u64_le> surface_height_minus1;
 };
 
-Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_)
-    : gpu(gpu_),
+Vic::Vic(Host1x& host1x_, std::shared_ptr<Nvdec> nvdec_processor_)
+    : host1x(host1x_),
       nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {}
 
 Vic::~Vic() = default;
@@ -81,7 +81,7 @@ void Vic::Execute() {
         LOG_ERROR(Service_NVDRV, "VIC Luma address not set.");
         return;
     }
-    const VicConfig config{gpu.MemoryManager().Read<u64>(config_struct_address + 0x20)};
+    const VicConfig config{host1x.MemoryManager().Read<u64>(config_struct_address + 0x20)};
     const AVFramePtr frame_ptr = nvdec_processor->GetFrame();
     const auto* frame = frame_ptr.get();
     if (!frame) {
@@ -159,12 +159,12 @@ void Vic::WriteRGBFrame(const AVFrame* frame, const VicConfig& config) {
         Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(),
                                 converted_frame_buf_addr, block_height, 0, 0);
 
-        gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
+        host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
     } else {
         // send pitch linear frame
         const size_t linear_size = width * height * 4;
-        gpu.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
-                                       linear_size);
+        host1x.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
+                                          linear_size);
     }
 }
 
@@ -192,8 +192,8 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
             luma_buffer[dst + x] = luma_src[src + x];
         }
     }
-    gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
-                                   luma_buffer.size());
+    host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
+                                      luma_buffer.size());
 
     // Chroma
     const std::size_t half_height = frame_height / 2;
@@ -234,8 +234,8 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
         ASSERT(false);
         break;
     }
-    gpu.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
-                                   chroma_buffer.size());
+    host1x.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
+                                      chroma_buffer.size());
 }
 
 } // namespace Host1x

+ 3 - 3
src/video_core/host1x/vic.h

@@ -10,10 +10,10 @@
 struct SwsContext;
 
 namespace Tegra {
-class GPU;
 
 namespace Host1x {
 
+class Host1x;
 class Nvdec;
 union VicConfig;
 
@@ -28,7 +28,7 @@ public:
         SetOutputSurfaceChromaUnusedOffset = 0x1ca
     };
 
-    explicit Vic(GPU& gpu, std::shared_ptr<Nvdec> nvdec_processor);
+    explicit Vic(Host1x& host1x, std::shared_ptr<Nvdec> nvdec_processor);
 
     ~Vic();
 
@@ -42,7 +42,7 @@ private:
 
     void WriteYUVFrame(const AVFrame* frame, const VicConfig& config);
 
-    GPU& gpu;
+    Host1x& host1x;
     std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
 
     /// Avoid reallocation of the following buffers every frame, as their