mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-25 22:57:22 +00:00
NVDRV: Refactor and add new NvMap.
This commit is contained in:
parent
a21b8824fb
commit
3cbe352c18
20 changed files with 558 additions and 45 deletions
|
@ -127,11 +127,14 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This constructor and assignment operator might be considered ambiguous:
|
BitField(T val) {
|
||||||
// Would they initialize the storage or just the bitfield?
|
Assign(val);
|
||||||
// Hence, delete them. Use the Assign method to set bitfield values!
|
}
|
||||||
BitField(T val) = delete;
|
|
||||||
BitField& operator=(T val) = delete;
|
BitField& operator=(T val) {
|
||||||
|
Assign(val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr BitField() noexcept = default;
|
constexpr BitField() noexcept = default;
|
||||||
|
|
||||||
|
|
|
@ -550,6 +550,12 @@ add_library(core STATIC
|
||||||
hle/service/ns/ns.h
|
hle/service/ns/ns.h
|
||||||
hle/service/ns/pdm_qry.cpp
|
hle/service/ns/pdm_qry.cpp
|
||||||
hle/service/ns/pdm_qry.h
|
hle/service/ns/pdm_qry.h
|
||||||
|
hle/service/nvdrv/core/container.cpp
|
||||||
|
hle/service/nvdrv/core/container.h
|
||||||
|
hle/service/nvdrv/core/nvmap.cpp
|
||||||
|
hle/service/nvdrv/core/nvmap.h
|
||||||
|
hle/service/nvdrv/core/syncpoint_manager.cpp
|
||||||
|
hle/service/nvdrv/core/syncpoint_manager.h
|
||||||
hle/service/nvdrv/devices/nvdevice.h
|
hle/service/nvdrv/devices/nvdevice.h
|
||||||
hle/service/nvdrv/devices/nvdisp_disp0.cpp
|
hle/service/nvdrv/devices/nvdisp_disp0.cpp
|
||||||
hle/service/nvdrv/devices/nvdisp_disp0.h
|
hle/service/nvdrv/devices/nvdisp_disp0.h
|
||||||
|
@ -578,8 +584,6 @@ add_library(core STATIC
|
||||||
hle/service/nvdrv/nvdrv_interface.h
|
hle/service/nvdrv/nvdrv_interface.h
|
||||||
hle/service/nvdrv/nvmemp.cpp
|
hle/service/nvdrv/nvmemp.cpp
|
||||||
hle/service/nvdrv/nvmemp.h
|
hle/service/nvdrv/nvmemp.h
|
||||||
hle/service/nvdrv/syncpoint_manager.cpp
|
|
||||||
hle/service/nvdrv/syncpoint_manager.h
|
|
||||||
hle/service/nvflinger/binder.h
|
hle/service/nvflinger/binder.h
|
||||||
hle/service/nvflinger/buffer_item.h
|
hle/service/nvflinger/buffer_item.h
|
||||||
hle/service/nvflinger/buffer_item_consumer.cpp
|
hle/service/nvflinger/buffer_item_consumer.cpp
|
||||||
|
|
41
src/core/hle/service/nvdrv/core/container.cpp
Normal file
41
src/core/hle/service/nvdrv/core/container.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2021 yuzu emulator team
|
||||||
|
// Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
|
struct ContainerImpl {
|
||||||
|
ContainerImpl(Tegra::GPU& gpu_) : file{}, manager{gpu_} {}
|
||||||
|
NvMap file;
|
||||||
|
SyncpointManager manager;
|
||||||
|
};
|
||||||
|
|
||||||
|
Container::Container(Tegra::GPU& gpu_) {
|
||||||
|
impl = std::make_unique<ContainerImpl>(gpu_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Container::~Container() = default;
|
||||||
|
|
||||||
|
NvMap& Container::GetNvMapFile() {
|
||||||
|
return impl->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NvMap& Container::GetNvMapFile() const {
|
||||||
|
return impl->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncpointManager& Container::GetSyncpointManager() {
|
||||||
|
return impl->manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SyncpointManager& Container::GetSyncpointManager() const {
|
||||||
|
return impl->manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
38
src/core/hle/service/nvdrv/core/container.h
Normal file
38
src/core/hle/service/nvdrv/core/container.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2021 yuzu emulator team
|
||||||
|
// Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
|
class GPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
|
class NvMap;
|
||||||
|
class SyncpointManager;
|
||||||
|
|
||||||
|
struct ContainerImpl;
|
||||||
|
|
||||||
|
class Container {
|
||||||
|
public:
|
||||||
|
Container(Tegra::GPU& gpu_);
|
||||||
|
~Container();
|
||||||
|
|
||||||
|
NvMap& GetNvMapFile();
|
||||||
|
|
||||||
|
const NvMap& GetNvMapFile() const;
|
||||||
|
|
||||||
|
SyncpointManager& GetSyncpointManager();
|
||||||
|
|
||||||
|
const SyncpointManager& GetSyncpointManager() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<ContainerImpl> impl;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
245
src/core/hle/service/nvdrv/core/nvmap.cpp
Normal file
245
src/core/hle/service/nvdrv/core/nvmap.cpp
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
// Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/alignment.h"
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
using Core::Memory::YUZU_PAGESIZE;
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
NvMap::Handle::Handle(u64 size, Id id) : size(size), aligned_size(size), orig_size(size), id(id) {}
|
||||||
|
|
||||||
|
NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) {
|
||||||
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
|
// Handles cannot be allocated twice
|
||||||
|
if (allocated) [[unlikely]]
|
||||||
|
return NvResult::AccessDenied;
|
||||||
|
|
||||||
|
flags = pFlags;
|
||||||
|
kind = pKind;
|
||||||
|
align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign;
|
||||||
|
|
||||||
|
// This flag is only applicable for handles with an address passed
|
||||||
|
if (pAddress)
|
||||||
|
flags.keep_uncached_after_free = 0;
|
||||||
|
else
|
||||||
|
LOG_CRITICAL(Service_NVDRV,
|
||||||
|
"Mapping nvmap handles without a CPU side address is unimplemented!");
|
||||||
|
|
||||||
|
size = Common::AlignUp(size, YUZU_PAGESIZE);
|
||||||
|
aligned_size = Common::AlignUp(size, align);
|
||||||
|
address = pAddress;
|
||||||
|
|
||||||
|
// TODO: pin init
|
||||||
|
|
||||||
|
allocated = true;
|
||||||
|
|
||||||
|
return NvResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
NvResult NvMap::Handle::Duplicate(bool internal_session) {
|
||||||
|
// Unallocated handles cannot be duplicated as duplication requires memory accounting (in HOS)
|
||||||
|
if (!allocated) [[unlikely]]
|
||||||
|
return NvResult::BadValue;
|
||||||
|
|
||||||
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
|
// If we internally use FromId the duplication tracking of handles won't work accurately due to
|
||||||
|
// us not implementing per-process handle refs.
|
||||||
|
if (internal_session)
|
||||||
|
internal_dupes++;
|
||||||
|
else
|
||||||
|
dupes++;
|
||||||
|
|
||||||
|
return NvResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
NvMap::NvMap() = default;
|
||||||
|
|
||||||
|
void NvMap::AddHandle(std::shared_ptr<Handle> handleDesc) {
|
||||||
|
std::scoped_lock lock(handles_lock);
|
||||||
|
|
||||||
|
handles.emplace(handleDesc->id, std::move(handleDesc));
|
||||||
|
}
|
||||||
|
|
||||||
|
void NvMap::UnmapHandle(Handle& handleDesc) {
|
||||||
|
// Remove pending unmap queue entry if needed
|
||||||
|
if (handleDesc.unmap_queue_entry) {
|
||||||
|
unmap_queue.erase(*handleDesc.unmap_queue_entry);
|
||||||
|
handleDesc.unmap_queue_entry.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free and unmap the handle from the SMMU
|
||||||
|
/*
|
||||||
|
state.soc->smmu.Unmap(handleDesc.pin_virt_address, static_cast<u32>(handleDesc.aligned_size));
|
||||||
|
smmuAllocator.Free(handleDesc.pin_virt_address, static_cast<u32>(handleDesc.aligned_size));
|
||||||
|
handleDesc.pin_virt_address = 0;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NvMap::TryRemoveHandle(const Handle& handleDesc) {
|
||||||
|
// No dupes left, we can remove from handle map
|
||||||
|
if (handleDesc.dupes == 0 && handleDesc.internal_dupes == 0) {
|
||||||
|
std::scoped_lock lock(handles_lock);
|
||||||
|
|
||||||
|
auto it{handles.find(handleDesc.id)};
|
||||||
|
if (it != handles.end())
|
||||||
|
handles.erase(it);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NvResult NvMap::CreateHandle(u64 size, std::shared_ptr<NvMap::Handle>& result_out) {
|
||||||
|
if (!size) [[unlikely]]
|
||||||
|
return NvResult::BadValue;
|
||||||
|
|
||||||
|
u32 id{next_handle_id.fetch_add(HandleIdIncrement, std::memory_order_relaxed)};
|
||||||
|
auto handleDesc{std::make_shared<Handle>(size, id)};
|
||||||
|
AddHandle(handleDesc);
|
||||||
|
|
||||||
|
result_out = handleDesc;
|
||||||
|
return NvResult::Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<NvMap::Handle> NvMap::GetHandle(Handle::Id handle) {
|
||||||
|
std::scoped_lock lock(handles_lock);
|
||||||
|
try {
|
||||||
|
return handles.at(handle);
|
||||||
|
} catch ([[maybe_unused]] std::out_of_range& e) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
||||||
|
UNIMPLEMENTED_MSG("pinning");
|
||||||
|
return 0;
|
||||||
|
/*
|
||||||
|
auto handleDesc{GetHandle(handle)};
|
||||||
|
if (!handleDesc)
|
||||||
|
[[unlikely]] return 0;
|
||||||
|
|
||||||
|
std::scoped_lock lock(handleDesc->mutex);
|
||||||
|
if (!handleDesc->pins) {
|
||||||
|
// If we're in the unmap queue we can just remove ourselves and return since we're already
|
||||||
|
// mapped
|
||||||
|
{
|
||||||
|
// Lock now to prevent our queue entry from being removed for allocation in-between the
|
||||||
|
// following check and erase
|
||||||
|
std::scoped_lock queueLock(unmap_queue_lock);
|
||||||
|
if (handleDesc->unmap_queue_entry) {
|
||||||
|
unmap_queue.erase(*handleDesc->unmap_queue_entry);
|
||||||
|
handleDesc->unmap_queue_entry.reset();
|
||||||
|
|
||||||
|
handleDesc->pins++;
|
||||||
|
return handleDesc->pin_virt_address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not then allocate some space and map it
|
||||||
|
u32 address{};
|
||||||
|
while (!(address = smmuAllocator.Allocate(static_cast<u32>(handleDesc->aligned_size)))) {
|
||||||
|
// Free handles until the allocation succeeds
|
||||||
|
std::scoped_lock queueLock(unmap_queue_lock);
|
||||||
|
if (auto freeHandleDesc{unmap_queue.front()}) {
|
||||||
|
// Handles in the unmap queue are guaranteed not to be pinned so don't bother
|
||||||
|
// checking if they are before unmapping
|
||||||
|
std::scoped_lock freeLock(freeHandleDesc->mutex);
|
||||||
|
if (handleDesc->pin_virt_address)
|
||||||
|
UnmapHandle(*freeHandleDesc);
|
||||||
|
} else {
|
||||||
|
LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
state.soc->smmu.Map(address, handleDesc->GetPointer(),
|
||||||
|
static_cast<u32>(handleDesc->aligned_size));
|
||||||
|
handleDesc->pin_virt_address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDesc->pins++;
|
||||||
|
return handleDesc->pin_virt_address;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void NvMap::UnpinHandle(Handle::Id handle) {
|
||||||
|
UNIMPLEMENTED_MSG("Unpinning");
|
||||||
|
/*
|
||||||
|
auto handleDesc{GetHandle(handle)};
|
||||||
|
if (!handleDesc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::scoped_lock lock(handleDesc->mutex);
|
||||||
|
if (--handleDesc->pins < 0) {
|
||||||
|
LOG_WARNING(Service_NVDRV, "Pin count imbalance detected!");
|
||||||
|
} else if (!handleDesc->pins) {
|
||||||
|
std::scoped_lock queueLock(unmap_queue_lock);
|
||||||
|
|
||||||
|
// Add to the unmap queue allowing this handle's memory to be freed if needed
|
||||||
|
unmap_queue.push_back(handleDesc);
|
||||||
|
handleDesc->unmap_queue_entry = std::prev(unmap_queue.end());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
|
||||||
|
std::weak_ptr<Handle> hWeak{GetHandle(handle)};
|
||||||
|
FreeInfo freeInfo;
|
||||||
|
|
||||||
|
// We use a weak ptr here so we can tell when the handle has been freed and report that back to
|
||||||
|
// guest
|
||||||
|
if (auto handleDesc = hWeak.lock()) {
|
||||||
|
std::scoped_lock lock(handleDesc->mutex);
|
||||||
|
|
||||||
|
if (internal_session) {
|
||||||
|
if (--handleDesc->internal_dupes < 0)
|
||||||
|
LOG_WARNING(Service_NVDRV, "Internal duplicate count imbalance detected!");
|
||||||
|
} else {
|
||||||
|
if (--handleDesc->dupes < 0) {
|
||||||
|
LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!");
|
||||||
|
} else if (handleDesc->dupes == 0) {
|
||||||
|
// Force unmap the handle
|
||||||
|
if (handleDesc->pin_virt_address) {
|
||||||
|
std::scoped_lock queueLock(unmap_queue_lock);
|
||||||
|
UnmapHandle(*handleDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDesc->pins = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to remove the shared ptr to the handle from the map, if nothing else is using the
|
||||||
|
// handle then it will now be freed when `handleDesc` goes out of scope
|
||||||
|
if (TryRemoveHandle(*handleDesc))
|
||||||
|
LOG_ERROR(Service_NVDRV, "Removed nvmap handle: {}", handle);
|
||||||
|
else
|
||||||
|
LOG_ERROR(Service_NVDRV,
|
||||||
|
"Tried to free nvmap handle: {} but didn't as it still has duplicates",
|
||||||
|
handle);
|
||||||
|
|
||||||
|
freeInfo = {
|
||||||
|
.address = handleDesc->address,
|
||||||
|
.size = handleDesc->size,
|
||||||
|
.was_uncached = handleDesc->flags.map_uncached.Value() != 0,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed
|
||||||
|
if (!hWeak.expired()) {
|
||||||
|
LOG_ERROR(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
|
||||||
|
freeInfo.address = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return freeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
155
src/core/hle/service/nvdrv/core/nvmap.h
Normal file
155
src/core/hle/service/nvdrv/core/nvmap.h
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
// Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
/**
|
||||||
|
* @brief The nvmap core class holds the global state for nvmap and provides methods to manage
|
||||||
|
* handles
|
||||||
|
*/
|
||||||
|
class NvMap {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief A handle to a contiguous block of memory in an application's address space
|
||||||
|
*/
|
||||||
|
struct Handle {
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
|
u64 align{}; //!< The alignment to use when pinning the handle onto the SMMU
|
||||||
|
u64 size; //!< Page-aligned size of the memory the handle refers to
|
||||||
|
u64 aligned_size; //!< `align`-aligned size of the memory the handle refers to
|
||||||
|
u64 orig_size; //!< Original unaligned size of the memory this handle refers to
|
||||||
|
|
||||||
|
s32 dupes{1}; //!< How many guest references there are to this handle
|
||||||
|
s32 internal_dupes{0}; //!< How many emulator-internal references there are to this handle
|
||||||
|
|
||||||
|
using Id = u32;
|
||||||
|
Id id; //!< A globally unique identifier for this handle
|
||||||
|
|
||||||
|
s32 pins{};
|
||||||
|
u32 pin_virt_address{};
|
||||||
|
std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{};
|
||||||
|
|
||||||
|
union Flags {
|
||||||
|
BitField<0, 1, u32> map_uncached; //!< If the handle should be mapped as uncached
|
||||||
|
BitField<2, 1, u32> keep_uncached_after_free; //!< Only applicable when the handle was
|
||||||
|
//!< allocated with a fixed address
|
||||||
|
BitField<4, 1, u32> _unk0_; //!< Passed to IOVMM for pins
|
||||||
|
} flags{};
|
||||||
|
static_assert(sizeof(Flags) == sizeof(u32));
|
||||||
|
|
||||||
|
u64 address{}; //!< The memory location in the guest's AS that this handle corresponds to,
|
||||||
|
//!< this can also be in the nvdrv tmem
|
||||||
|
bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC
|
||||||
|
//!< call
|
||||||
|
|
||||||
|
u8 kind{}; //!< Used for memory compression
|
||||||
|
bool allocated{}; //!< If the handle has been allocated with `Alloc`
|
||||||
|
|
||||||
|
Handle(u64 size, Id id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets up the handle with the given memory config, can allocate memory from the tmem
|
||||||
|
* if a 0 address is passed
|
||||||
|
*/
|
||||||
|
[[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Increases the dupe counter of the handle for the given session
|
||||||
|
*/
|
||||||
|
[[nodiscard]] NvResult Duplicate(bool internal_session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Obtains a pointer to the handle's memory and marks the handle it as having been
|
||||||
|
* mapped
|
||||||
|
*/
|
||||||
|
u8* GetPointer() {
|
||||||
|
if (!address) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_shared_mem_mapped = true;
|
||||||
|
return reinterpret_cast<u8*>(address);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
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::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};
|
||||||
|
|
||||||
|
void AddHandle(std::shared_ptr<Handle> handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmaps and frees the SMMU memory region a handle is mapped to
|
||||||
|
* @note Both `unmap_queue_lock` and `handleDesc.mutex` MUST be locked when calling this
|
||||||
|
*/
|
||||||
|
void UnmapHandle(Handle& handleDesc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes a handle from the map taking its dupes into account
|
||||||
|
* @note handleDesc.mutex MUST be locked when calling this
|
||||||
|
* @return If the handle was removed from the map
|
||||||
|
*/
|
||||||
|
bool TryRemoveHandle(const Handle& handleDesc);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Encapsulates the result of a FreeHandle operation
|
||||||
|
*/
|
||||||
|
struct FreeInfo {
|
||||||
|
u64 address; //!< Address the handle referred to before deletion
|
||||||
|
u64 size; //!< Page-aligned handle size
|
||||||
|
bool was_uncached; //!< If the handle was allocated as uncached
|
||||||
|
};
|
||||||
|
|
||||||
|
NvMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an unallocated handle of the given size
|
||||||
|
*/
|
||||||
|
[[nodiscard]] NvResult CreateHandle(u64 size, std::shared_ptr<NvMap::Handle>& result_out);
|
||||||
|
|
||||||
|
std::shared_ptr<Handle> GetHandle(Handle::Id handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maps a handle into the SMMU address space
|
||||||
|
* @note This operation is refcounted, the number of calls to this must eventually match the
|
||||||
|
* number of calls to `UnpinHandle`
|
||||||
|
* @return The SMMU virtual address that the handle has been mapped to
|
||||||
|
*/
|
||||||
|
u32 PinHandle(Handle::Id handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief When this has been called an equal number of times to `PinHandle` for the supplied
|
||||||
|
* handle it will be added to a list of handles to be freed when necessary
|
||||||
|
*/
|
||||||
|
void UnpinHandle(Handle::Id handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tries to free a handle and remove a single dupe
|
||||||
|
* @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned
|
||||||
|
* describing the prior state of the handle
|
||||||
|
*/
|
||||||
|
std::optional<FreeInfo> FreeHandle(Handle::Id handle, bool internal_session);
|
||||||
|
};
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
|
@ -2,10 +2,10 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/hle/service/nvdrv/syncpoint_manager.h"
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {}
|
SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {}
|
||||||
|
|
||||||
|
@ -35,4 +35,4 @@ u32 SyncpointManager::IncreaseSyncpoint(u32 syncpoint_id, u32 value) {
|
||||||
return GetSyncpointMax(syncpoint_id);
|
return GetSyncpointMax(syncpoint_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia::NvCore
|
|
@ -13,7 +13,7 @@ namespace Tegra {
|
||||||
class GPU;
|
class GPU;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
class SyncpointManager final {
|
class SyncpointManager final {
|
||||||
public:
|
public:
|
||||||
|
@ -81,4 +81,4 @@ private:
|
||||||
Tegra::GPU& gpu;
|
Tegra::GPU& gpu;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia::NvCore
|
|
@ -12,15 +12,17 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/kernel/k_writable_event.h"
|
#include "core/hle/kernel/k_writable_event.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
|
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
|
|
||||||
namespace Service::Nvidia::Devices {
|
namespace Service::Nvidia::Devices {
|
||||||
|
|
||||||
nvhost_ctrl::nvhost_ctrl(Core::System& system_, EventInterface& events_interface_,
|
nvhost_ctrl::nvhost_ctrl(Core::System& system_, EventInterface& events_interface_,
|
||||||
SyncpointManager& syncpoint_manager_)
|
NvCore::Container& core_)
|
||||||
: nvdevice{system_}, events_interface{events_interface_}, syncpoint_manager{
|
: nvdevice{system_}, events_interface{events_interface_}, core{core_},
|
||||||
syncpoint_manager_} {}
|
syncpoint_manager{core_.GetSyncpointManager()} {}
|
||||||
nvhost_ctrl::~nvhost_ctrl() = default;
|
nvhost_ctrl::~nvhost_ctrl() = default;
|
||||||
|
|
||||||
NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
|
|
@ -10,12 +10,17 @@
|
||||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||||
|
|
||||||
|
namespace Service::Nvidia::NvCore {
|
||||||
|
class Container;
|
||||||
|
class SyncpointManager;
|
||||||
|
} // namespace Service::Nvidia::NvCore
|
||||||
|
|
||||||
namespace Service::Nvidia::Devices {
|
namespace Service::Nvidia::Devices {
|
||||||
|
|
||||||
class nvhost_ctrl final : public nvdevice {
|
class nvhost_ctrl final : public nvdevice {
|
||||||
public:
|
public:
|
||||||
explicit nvhost_ctrl(Core::System& system_, EventInterface& events_interface_,
|
explicit nvhost_ctrl(Core::System& system_, EventInterface& events_interface_,
|
||||||
SyncpointManager& syncpoint_manager_);
|
NvCore::Container& core);
|
||||||
~nvhost_ctrl() override;
|
~nvhost_ctrl() override;
|
||||||
|
|
||||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
@ -145,7 +150,8 @@ private:
|
||||||
NvResult FreeEvent(u32 slot);
|
NvResult FreeEvent(u32 slot);
|
||||||
|
|
||||||
EventInterface& events_interface;
|
EventInterface& events_interface;
|
||||||
SyncpointManager& syncpoint_manager;
|
NvCore::Container& core;
|
||||||
|
NvCore::SyncpointManager& syncpoint_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::Devices
|
} // namespace Service::Nvidia::Devices
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
|
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
|
||||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||||
#include "core/hle/service/nvdrv/syncpoint_manager.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
|
|
||||||
|
@ -22,10 +23,10 @@ Tegra::CommandHeader BuildFenceAction(Tegra::GPU::FenceOperation op, u32 syncpoi
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
EventInterface& events_interface_, SyncpointManager& syncpoint_manager_)
|
EventInterface& events_interface_, NvCore::Container& core_)
|
||||||
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, events_interface{events_interface_},
|
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, events_interface{events_interface_},
|
||||||
syncpoint_manager{syncpoint_manager_} {
|
core{core_}, syncpoint_manager{core_.GetSyncpointManager()} {
|
||||||
channel_fence.id = syncpoint_manager_.AllocateSyncpoint();
|
channel_fence.id = syncpoint_manager.AllocateSyncpoint();
|
||||||
channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id);
|
channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id);
|
||||||
sm_exception_breakpoint_int_report_event =
|
sm_exception_breakpoint_int_report_event =
|
||||||
events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointInt");
|
events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointInt");
|
||||||
|
|
|
@ -14,7 +14,12 @@
|
||||||
#include "video_core/dma_pusher.h"
|
#include "video_core/dma_pusher.h"
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia {
|
||||||
|
|
||||||
|
namespace NvCore {
|
||||||
|
class Container;
|
||||||
class SyncpointManager;
|
class SyncpointManager;
|
||||||
|
} // namespace NvCore
|
||||||
|
|
||||||
class EventInterface;
|
class EventInterface;
|
||||||
} // namespace Service::Nvidia
|
} // namespace Service::Nvidia
|
||||||
|
|
||||||
|
@ -24,7 +29,7 @@ class nvmap;
|
||||||
class nvhost_gpu final : public nvdevice {
|
class nvhost_gpu final : public nvdevice {
|
||||||
public:
|
public:
|
||||||
explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
EventInterface& events_interface_, SyncpointManager& syncpoint_manager_);
|
EventInterface& events_interface_, NvCore::Container& core);
|
||||||
~nvhost_gpu() override;
|
~nvhost_gpu() override;
|
||||||
|
|
||||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
@ -196,7 +201,8 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<nvmap> nvmap_dev;
|
std::shared_ptr<nvmap> nvmap_dev;
|
||||||
EventInterface& events_interface;
|
EventInterface& events_interface;
|
||||||
SyncpointManager& syncpoint_manager;
|
NvCore::Container& core;
|
||||||
|
NvCore::SyncpointManager& syncpoint_manager;
|
||||||
NvFence channel_fence;
|
NvFence channel_fence;
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
namespace Service::Nvidia::Devices {
|
namespace Service::Nvidia::Devices {
|
||||||
|
|
||||||
nvhost_nvdec::nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
nvhost_nvdec::nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_)
|
NvCore::Container& core)
|
||||||
: nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {}
|
: nvhost_nvdec_common{system_, std::move(nvmap_dev_), core} {}
|
||||||
nvhost_nvdec::~nvhost_nvdec() = default;
|
nvhost_nvdec::~nvhost_nvdec() = default;
|
||||||
|
|
||||||
NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Service::Nvidia::Devices {
|
||||||
class nvhost_nvdec final : public nvhost_nvdec_common {
|
class nvhost_nvdec final : public nvhost_nvdec_common {
|
||||||
public:
|
public:
|
||||||
explicit nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
explicit nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_);
|
NvCore::Container& core);
|
||||||
~nvhost_nvdec() override;
|
~nvhost_nvdec() override;
|
||||||
|
|
||||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h"
|
#include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvmap.h"
|
#include "core/hle/service/nvdrv/devices/nvmap.h"
|
||||||
#include "core/hle/service/nvdrv/syncpoint_manager.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
@ -45,8 +46,9 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_)
|
NvCore::Container& core_)
|
||||||
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, syncpoint_manager{syncpoint_manager_} {}
|
: nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, core{core_},
|
||||||
|
syncpoint_manager{core.GetSyncpointManager()} {}
|
||||||
nvhost_nvdec_common::~nvhost_nvdec_common() = default;
|
nvhost_nvdec_common::~nvhost_nvdec_common() = default;
|
||||||
|
|
||||||
NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
|
NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) {
|
||||||
|
|
|
@ -9,7 +9,11 @@
|
||||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia {
|
||||||
|
|
||||||
|
namespace NvCore {
|
||||||
class SyncpointManager;
|
class SyncpointManager;
|
||||||
|
class Container;
|
||||||
|
} // namespace NvCore
|
||||||
|
|
||||||
namespace Devices {
|
namespace Devices {
|
||||||
class nvmap;
|
class nvmap;
|
||||||
|
@ -17,7 +21,7 @@ class nvmap;
|
||||||
class nvhost_nvdec_common : public nvdevice {
|
class nvhost_nvdec_common : public nvdevice {
|
||||||
public:
|
public:
|
||||||
explicit nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
explicit nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_);
|
NvCore::Container& core);
|
||||||
~nvhost_nvdec_common() override;
|
~nvhost_nvdec_common() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -114,7 +118,8 @@ protected:
|
||||||
s32_le nvmap_fd{};
|
s32_le nvmap_fd{};
|
||||||
u32_le submit_timeout{};
|
u32_le submit_timeout{};
|
||||||
std::shared_ptr<nvmap> nvmap_dev;
|
std::shared_ptr<nvmap> nvmap_dev;
|
||||||
SyncpointManager& syncpoint_manager;
|
NvCore::Container& core;
|
||||||
|
NvCore::SyncpointManager& syncpoint_manager;
|
||||||
std::array<u32, MaxSyncPoints> device_syncpoints{};
|
std::array<u32, MaxSyncPoints> device_syncpoints{};
|
||||||
};
|
};
|
||||||
}; // namespace Devices
|
}; // namespace Devices
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
namespace Service::Nvidia::Devices {
|
namespace Service::Nvidia::Devices {
|
||||||
nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_)
|
NvCore::Container& core)
|
||||||
: nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {}
|
: nvhost_nvdec_common{system_, std::move(nvmap_dev_), core} {}
|
||||||
|
|
||||||
nvhost_vic::~nvhost_vic() = default;
|
nvhost_vic::~nvhost_vic() = default;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices {
|
||||||
class nvhost_vic final : public nvhost_nvdec_common {
|
class nvhost_vic final : public nvhost_nvdec_common {
|
||||||
public:
|
public:
|
||||||
explicit nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
explicit nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_);
|
NvCore::Container& core);
|
||||||
~nvhost_vic();
|
~nvhost_vic();
|
||||||
|
|
||||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/kernel/k_writable_event.h"
|
#include "core/hle/kernel/k_writable_event.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
#include "core/hle/service/nvdrv/devices/nvdevice.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
|
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
|
||||||
|
@ -24,8 +25,8 @@
|
||||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||||
#include "core/hle/service/nvdrv/nvdrv_interface.h"
|
#include "core/hle/service/nvdrv/nvdrv_interface.h"
|
||||||
#include "core/hle/service/nvdrv/nvmemp.h"
|
#include "core/hle/service/nvdrv/nvmemp.h"
|
||||||
#include "core/hle/service/nvdrv/syncpoint_manager.h"
|
|
||||||
#include "core/hle/service/nvflinger/nvflinger.h"
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
||||||
|
#include "video_core/gpu.h"
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia {
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ void EventInterface::Create(u32 event_id) {
|
||||||
const u64 mask = 1ULL << event_id;
|
const u64 mask = 1ULL << event_id;
|
||||||
fails[event_id] = 0;
|
fails[event_id] = 0;
|
||||||
events_mask |= mask;
|
events_mask |= mask;
|
||||||
|
assigned_syncpt[event_id] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventInterface::Free(u32 event_id) {
|
void EventInterface::Free(u32 event_id) {
|
||||||
|
@ -135,22 +137,22 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Module(Core::System& system)
|
Module::Module(Core::System& system)
|
||||||
: syncpoint_manager{system.GPU()}, service_context{system, "nvdrv"}, events_interface{*this} {
|
: service_context{system, "nvdrv"}, events_interface{*this}, container{system.GPU()} {
|
||||||
auto nvmap_dev = std::make_shared<Devices::nvmap>(system);
|
auto nvmap_dev = std::make_shared<Devices::nvmap>(system);
|
||||||
devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev);
|
devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev);
|
||||||
devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>(
|
devices["/dev/nvhost-gpu"] =
|
||||||
system, nvmap_dev, events_interface, syncpoint_manager);
|
std::make_shared<Devices::nvhost_gpu>(system, nvmap_dev, events_interface, container);
|
||||||
devices["/dev/nvhost-ctrl-gpu"] =
|
devices["/dev/nvhost-ctrl-gpu"] =
|
||||||
std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface);
|
std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface);
|
||||||
devices["/dev/nvmap"] = nvmap_dev;
|
devices["/dev/nvmap"] = nvmap_dev;
|
||||||
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev);
|
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev);
|
||||||
devices["/dev/nvhost-ctrl"] =
|
devices["/dev/nvhost-ctrl"] =
|
||||||
std::make_shared<Devices::nvhost_ctrl>(system, events_interface, syncpoint_manager);
|
std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container);
|
||||||
devices["/dev/nvhost-nvdec"] =
|
devices["/dev/nvhost-nvdec"] =
|
||||||
std::make_shared<Devices::nvhost_nvdec>(system, nvmap_dev, syncpoint_manager);
|
std::make_shared<Devices::nvhost_nvdec>(system, nvmap_dev, container);
|
||||||
devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system);
|
devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system);
|
||||||
devices["/dev/nvhost-vic"] =
|
devices["/dev/nvhost-vic"] =
|
||||||
std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager);
|
std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::~Module() = default;
|
Module::~Module() = default;
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/kernel_helpers.h"
|
#include "core/hle/service/kernel_helpers.h"
|
||||||
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
#include "core/hle/service/nvdrv/syncpoint_manager.h"
|
|
||||||
#include "core/hle/service/nvflinger/ui/fence.h"
|
#include "core/hle/service/nvflinger/ui/fence.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
@ -31,7 +31,10 @@ class NVFlinger;
|
||||||
|
|
||||||
namespace Service::Nvidia {
|
namespace Service::Nvidia {
|
||||||
|
|
||||||
|
namespace NvCore {
|
||||||
|
class Container;
|
||||||
class SyncpointManager;
|
class SyncpointManager;
|
||||||
|
} // namespace NvCore
|
||||||
|
|
||||||
namespace Devices {
|
namespace Devices {
|
||||||
class nvdevice;
|
class nvdevice;
|
||||||
|
@ -126,9 +129,6 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class EventInterface;
|
friend class EventInterface;
|
||||||
|
|
||||||
/// Manages syncpoints on the host
|
|
||||||
SyncpointManager syncpoint_manager;
|
|
||||||
|
|
||||||
/// Id to use for the next open file descriptor.
|
/// Id to use for the next open file descriptor.
|
||||||
DeviceFD next_fd = 1;
|
DeviceFD next_fd = 1;
|
||||||
|
|
||||||
|
@ -142,6 +142,9 @@ private:
|
||||||
|
|
||||||
EventInterface events_interface;
|
EventInterface events_interface;
|
||||||
|
|
||||||
|
/// Manages syncpoints on the host
|
||||||
|
NvCore::Container container;
|
||||||
|
|
||||||
void CreateEvent(u32 event_id);
|
void CreateEvent(u32 event_id);
|
||||||
void FreeEvent(u32 event_id);
|
void FreeEvent(u32 event_id);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue