NVDRV: Refactor Host1x
This commit is contained in:
parent
668e80a9f4
commit
2931101e6f
33 changed files with 201 additions and 173 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(), ¶ms, 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(), ¶ms, 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(¶ms, 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue