diff options
Diffstat (limited to 'src')
20 files changed, 558 insertions, 45 deletions
diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 7e1df62b1..368b7b98c 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h | |||
| @@ -127,11 +127,14 @@ public: | |||
| 127 | } | 127 | } |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | // This constructor and assignment operator might be considered ambiguous: | 130 | BitField(T val) { |
| 131 | // Would they initialize the storage or just the bitfield? | 131 | Assign(val); |
| 132 | // Hence, delete them. Use the Assign method to set bitfield values! | 132 | } |
| 133 | BitField(T val) = delete; | 133 | |
| 134 | BitField& operator=(T val) = delete; | 134 | BitField& operator=(T val) { |
| 135 | Assign(val); | ||
| 136 | return *this; | ||
| 137 | } | ||
| 135 | 138 | ||
| 136 | constexpr BitField() noexcept = default; | 139 | constexpr BitField() noexcept = default; |
| 137 | 140 | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8e3fd4505..3ef19f9c2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -550,6 +550,12 @@ add_library(core STATIC | |||
| 550 | hle/service/ns/ns.h | 550 | hle/service/ns/ns.h |
| 551 | hle/service/ns/pdm_qry.cpp | 551 | hle/service/ns/pdm_qry.cpp |
| 552 | hle/service/ns/pdm_qry.h | 552 | hle/service/ns/pdm_qry.h |
| 553 | hle/service/nvdrv/core/container.cpp | ||
| 554 | hle/service/nvdrv/core/container.h | ||
| 555 | hle/service/nvdrv/core/nvmap.cpp | ||
| 556 | hle/service/nvdrv/core/nvmap.h | ||
| 557 | hle/service/nvdrv/core/syncpoint_manager.cpp | ||
| 558 | hle/service/nvdrv/core/syncpoint_manager.h | ||
| 553 | hle/service/nvdrv/devices/nvdevice.h | 559 | hle/service/nvdrv/devices/nvdevice.h |
| 554 | hle/service/nvdrv/devices/nvdisp_disp0.cpp | 560 | hle/service/nvdrv/devices/nvdisp_disp0.cpp |
| 555 | hle/service/nvdrv/devices/nvdisp_disp0.h | 561 | hle/service/nvdrv/devices/nvdisp_disp0.h |
| @@ -578,8 +584,6 @@ add_library(core STATIC | |||
| 578 | hle/service/nvdrv/nvdrv_interface.h | 584 | hle/service/nvdrv/nvdrv_interface.h |
| 579 | hle/service/nvdrv/nvmemp.cpp | 585 | hle/service/nvdrv/nvmemp.cpp |
| 580 | hle/service/nvdrv/nvmemp.h | 586 | hle/service/nvdrv/nvmemp.h |
| 581 | hle/service/nvdrv/syncpoint_manager.cpp | ||
| 582 | hle/service/nvdrv/syncpoint_manager.h | ||
| 583 | hle/service/nvflinger/binder.h | 587 | hle/service/nvflinger/binder.h |
| 584 | hle/service/nvflinger/buffer_item.h | 588 | hle/service/nvflinger/buffer_item.h |
| 585 | hle/service/nvflinger/buffer_item_consumer.cpp | 589 | hle/service/nvflinger/buffer_item_consumer.cpp |
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp new file mode 100644 index 000000000..97b5b2c86 --- /dev/null +++ b/src/core/hle/service/nvdrv/core/container.cpp | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) | ||
| 3 | // Licensed under GPLv2 or any later version | ||
| 4 | // Refer to the license.txt file included. | ||
| 5 | |||
| 6 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 7 | #include "core/hle/service/nvdrv/core/nvmap.h" | ||
| 8 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||
| 9 | #include "video_core/gpu.h" | ||
| 10 | |||
| 11 | namespace Service::Nvidia::NvCore { | ||
| 12 | |||
| 13 | struct ContainerImpl { | ||
| 14 | ContainerImpl(Tegra::GPU& gpu_) : file{}, manager{gpu_} {} | ||
| 15 | NvMap file; | ||
| 16 | SyncpointManager manager; | ||
| 17 | }; | ||
| 18 | |||
| 19 | Container::Container(Tegra::GPU& gpu_) { | ||
| 20 | impl = std::make_unique<ContainerImpl>(gpu_); | ||
| 21 | } | ||
| 22 | |||
| 23 | Container::~Container() = default; | ||
| 24 | |||
| 25 | NvMap& Container::GetNvMapFile() { | ||
| 26 | return impl->file; | ||
| 27 | } | ||
| 28 | |||
| 29 | const NvMap& Container::GetNvMapFile() const { | ||
| 30 | return impl->file; | ||
| 31 | } | ||
| 32 | |||
| 33 | SyncpointManager& Container::GetSyncpointManager() { | ||
| 34 | return impl->manager; | ||
| 35 | } | ||
| 36 | |||
| 37 | const SyncpointManager& Container::GetSyncpointManager() const { | ||
| 38 | return impl->manager; | ||
| 39 | } | ||
| 40 | |||
| 41 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/core/container.h b/src/core/hle/service/nvdrv/core/container.h new file mode 100644 index 000000000..91ac2305a --- /dev/null +++ b/src/core/hle/service/nvdrv/core/container.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) | ||
| 3 | // Licensed under GPLv2 or any later version | ||
| 4 | // Refer to the license.txt file included. | ||
| 5 | |||
| 6 | #pragma once | ||
| 7 | |||
| 8 | #include <memory> | ||
| 9 | |||
| 10 | namespace Tegra { | ||
| 11 | class GPU; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Service::Nvidia::NvCore { | ||
| 15 | |||
| 16 | class NvMap; | ||
| 17 | class SyncpointManager; | ||
| 18 | |||
| 19 | struct ContainerImpl; | ||
| 20 | |||
| 21 | class Container { | ||
| 22 | public: | ||
| 23 | Container(Tegra::GPU& gpu_); | ||
| 24 | ~Container(); | ||
| 25 | |||
| 26 | NvMap& GetNvMapFile(); | ||
| 27 | |||
| 28 | const NvMap& GetNvMapFile() const; | ||
| 29 | |||
| 30 | SyncpointManager& GetSyncpointManager(); | ||
| 31 | |||
| 32 | const SyncpointManager& GetSyncpointManager() const; | ||
| 33 | |||
| 34 | private: | ||
| 35 | std::unique_ptr<ContainerImpl> impl; | ||
| 36 | }; | ||
| 37 | |||
| 38 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp new file mode 100644 index 000000000..d3f227f52 --- /dev/null +++ b/src/core/hle/service/nvdrv/core/nvmap.cpp | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | // Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/alignment.h" | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "common/logging/log.h" | ||
| 8 | #include "core/hle/service/nvdrv/core/nvmap.h" | ||
| 9 | #include "core/memory.h" | ||
| 10 | |||
| 11 | using Core::Memory::YUZU_PAGESIZE; | ||
| 12 | |||
| 13 | namespace Service::Nvidia::NvCore { | ||
| 14 | NvMap::Handle::Handle(u64 size, Id id) : size(size), aligned_size(size), orig_size(size), id(id) {} | ||
| 15 | |||
| 16 | NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) { | ||
| 17 | std::scoped_lock lock(mutex); | ||
| 18 | |||
| 19 | // Handles cannot be allocated twice | ||
| 20 | if (allocated) [[unlikely]] | ||
| 21 | return NvResult::AccessDenied; | ||
| 22 | |||
| 23 | flags = pFlags; | ||
| 24 | kind = pKind; | ||
| 25 | align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign; | ||
| 26 | |||
| 27 | // This flag is only applicable for handles with an address passed | ||
| 28 | if (pAddress) | ||
| 29 | flags.keep_uncached_after_free = 0; | ||
| 30 | else | ||
| 31 | LOG_CRITICAL(Service_NVDRV, | ||
| 32 | "Mapping nvmap handles without a CPU side address is unimplemented!"); | ||
| 33 | |||
| 34 | size = Common::AlignUp(size, YUZU_PAGESIZE); | ||
| 35 | aligned_size = Common::AlignUp(size, align); | ||
| 36 | address = pAddress; | ||
| 37 | |||
| 38 | // TODO: pin init | ||
| 39 | |||
| 40 | allocated = true; | ||
| 41 | |||
| 42 | return NvResult::Success; | ||
| 43 | } | ||
| 44 | |||
| 45 | NvResult NvMap::Handle::Duplicate(bool internal_session) { | ||
| 46 | // Unallocated handles cannot be duplicated as duplication requires memory accounting (in HOS) | ||
| 47 | if (!allocated) [[unlikely]] | ||
| 48 | return NvResult::BadValue; | ||
| 49 | |||
| 50 | std::scoped_lock lock(mutex); | ||
| 51 | |||
| 52 | // If we internally use FromId the duplication tracking of handles won't work accurately due to | ||
| 53 | // us not implementing per-process handle refs. | ||
| 54 | if (internal_session) | ||
| 55 | internal_dupes++; | ||
| 56 | else | ||
| 57 | dupes++; | ||
| 58 | |||
| 59 | return NvResult::Success; | ||
| 60 | } | ||
| 61 | |||
| 62 | NvMap::NvMap() = default; | ||
| 63 | |||
| 64 | void NvMap::AddHandle(std::shared_ptr<Handle> handleDesc) { | ||
| 65 | std::scoped_lock lock(handles_lock); | ||
| 66 | |||
| 67 | handles.emplace(handleDesc->id, std::move(handleDesc)); | ||
| 68 | } | ||
| 69 | |||
| 70 | void NvMap::UnmapHandle(Handle& handleDesc) { | ||
| 71 | // Remove pending unmap queue entry if needed | ||
| 72 | if (handleDesc.unmap_queue_entry) { | ||
| 73 | unmap_queue.erase(*handleDesc.unmap_queue_entry); | ||
| 74 | handleDesc.unmap_queue_entry.reset(); | ||
| 75 | } | ||
| 76 | |||
| 77 | // Free and unmap the handle from the SMMU | ||
| 78 | /* | ||
| 79 | state.soc->smmu.Unmap(handleDesc.pin_virt_address, static_cast<u32>(handleDesc.aligned_size)); | ||
| 80 | smmuAllocator.Free(handleDesc.pin_virt_address, static_cast<u32>(handleDesc.aligned_size)); | ||
| 81 | handleDesc.pin_virt_address = 0; | ||
| 82 | */ | ||
| 83 | } | ||
| 84 | |||
| 85 | bool NvMap::TryRemoveHandle(const Handle& handleDesc) { | ||
| 86 | // No dupes left, we can remove from handle map | ||
| 87 | if (handleDesc.dupes == 0 && handleDesc.internal_dupes == 0) { | ||
| 88 | std::scoped_lock lock(handles_lock); | ||
| 89 | |||
| 90 | auto it{handles.find(handleDesc.id)}; | ||
| 91 | if (it != handles.end()) | ||
| 92 | handles.erase(it); | ||
| 93 | |||
| 94 | return true; | ||
| 95 | } else { | ||
| 96 | return false; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | NvResult NvMap::CreateHandle(u64 size, std::shared_ptr<NvMap::Handle>& result_out) { | ||
| 101 | if (!size) [[unlikely]] | ||
| 102 | return NvResult::BadValue; | ||
| 103 | |||
| 104 | u32 id{next_handle_id.fetch_add(HandleIdIncrement, std::memory_order_relaxed)}; | ||
| 105 | auto handleDesc{std::make_shared<Handle>(size, id)}; | ||
| 106 | AddHandle(handleDesc); | ||
| 107 | |||
| 108 | result_out = handleDesc; | ||
| 109 | return NvResult::Success; | ||
| 110 | } | ||
| 111 | |||
| 112 | std::shared_ptr<NvMap::Handle> NvMap::GetHandle(Handle::Id handle) { | ||
| 113 | std::scoped_lock lock(handles_lock); | ||
| 114 | try { | ||
| 115 | return handles.at(handle); | ||
| 116 | } catch ([[maybe_unused]] std::out_of_range& e) { | ||
| 117 | return nullptr; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | u32 NvMap::PinHandle(NvMap::Handle::Id handle) { | ||
| 122 | UNIMPLEMENTED_MSG("pinning"); | ||
| 123 | return 0; | ||
| 124 | /* | ||
| 125 | auto handleDesc{GetHandle(handle)}; | ||
| 126 | if (!handleDesc) | ||
| 127 | [[unlikely]] return 0; | ||
| 128 | |||
| 129 | std::scoped_lock lock(handleDesc->mutex); | ||
| 130 | if (!handleDesc->pins) { | ||
| 131 | // If we're in the unmap queue we can just remove ourselves and return since we're already | ||
| 132 | // mapped | ||
| 133 | { | ||
| 134 | // Lock now to prevent our queue entry from being removed for allocation in-between the | ||
| 135 | // following check and erase | ||
| 136 | std::scoped_lock queueLock(unmap_queue_lock); | ||
| 137 | if (handleDesc->unmap_queue_entry) { | ||
| 138 | unmap_queue.erase(*handleDesc->unmap_queue_entry); | ||
| 139 | handleDesc->unmap_queue_entry.reset(); | ||
| 140 | |||
| 141 | handleDesc->pins++; | ||
| 142 | return handleDesc->pin_virt_address; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | // If not then allocate some space and map it | ||
| 147 | u32 address{}; | ||
| 148 | while (!(address = smmuAllocator.Allocate(static_cast<u32>(handleDesc->aligned_size)))) { | ||
| 149 | // Free handles until the allocation succeeds | ||
| 150 | std::scoped_lock queueLock(unmap_queue_lock); | ||
| 151 | if (auto freeHandleDesc{unmap_queue.front()}) { | ||
| 152 | // Handles in the unmap queue are guaranteed not to be pinned so don't bother | ||
| 153 | // checking if they are before unmapping | ||
| 154 | std::scoped_lock freeLock(freeHandleDesc->mutex); | ||
| 155 | if (handleDesc->pin_virt_address) | ||
| 156 | UnmapHandle(*freeHandleDesc); | ||
| 157 | } else { | ||
| 158 | LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!"); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | state.soc->smmu.Map(address, handleDesc->GetPointer(), | ||
| 163 | static_cast<u32>(handleDesc->aligned_size)); | ||
| 164 | handleDesc->pin_virt_address = address; | ||
| 165 | } | ||
| 166 | |||
| 167 | handleDesc->pins++; | ||
| 168 | return handleDesc->pin_virt_address; | ||
| 169 | */ | ||
| 170 | } | ||
| 171 | |||
| 172 | void NvMap::UnpinHandle(Handle::Id handle) { | ||
| 173 | UNIMPLEMENTED_MSG("Unpinning"); | ||
| 174 | /* | ||
| 175 | auto handleDesc{GetHandle(handle)}; | ||
| 176 | if (!handleDesc) | ||
| 177 | return; | ||
| 178 | |||
| 179 | std::scoped_lock lock(handleDesc->mutex); | ||
| 180 | if (--handleDesc->pins < 0) { | ||
| 181 | LOG_WARNING(Service_NVDRV, "Pin count imbalance detected!"); | ||
| 182 | } else if (!handleDesc->pins) { | ||
| 183 | std::scoped_lock queueLock(unmap_queue_lock); | ||
| 184 | |||
| 185 | // Add to the unmap queue allowing this handle's memory to be freed if needed | ||
| 186 | unmap_queue.push_back(handleDesc); | ||
| 187 | handleDesc->unmap_queue_entry = std::prev(unmap_queue.end()); | ||
| 188 | } | ||
| 189 | */ | ||
| 190 | } | ||
| 191 | |||
| 192 | std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) { | ||
| 193 | std::weak_ptr<Handle> hWeak{GetHandle(handle)}; | ||
| 194 | FreeInfo freeInfo; | ||
| 195 | |||
| 196 | // We use a weak ptr here so we can tell when the handle has been freed and report that back to | ||
| 197 | // guest | ||
| 198 | if (auto handleDesc = hWeak.lock()) { | ||
| 199 | std::scoped_lock lock(handleDesc->mutex); | ||
| 200 | |||
| 201 | if (internal_session) { | ||
| 202 | if (--handleDesc->internal_dupes < 0) | ||
| 203 | LOG_WARNING(Service_NVDRV, "Internal duplicate count imbalance detected!"); | ||
| 204 | } else { | ||
| 205 | if (--handleDesc->dupes < 0) { | ||
| 206 | LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!"); | ||
| 207 | } else if (handleDesc->dupes == 0) { | ||
| 208 | // Force unmap the handle | ||
| 209 | if (handleDesc->pin_virt_address) { | ||
| 210 | std::scoped_lock queueLock(unmap_queue_lock); | ||
| 211 | UnmapHandle(*handleDesc); | ||
| 212 | } | ||
| 213 | |||
| 214 | handleDesc->pins = 0; | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | // Try to remove the shared ptr to the handle from the map, if nothing else is using the | ||
| 219 | // handle then it will now be freed when `handleDesc` goes out of scope | ||
| 220 | if (TryRemoveHandle(*handleDesc)) | ||
| 221 | LOG_ERROR(Service_NVDRV, "Removed nvmap handle: {}", handle); | ||
| 222 | else | ||
| 223 | LOG_ERROR(Service_NVDRV, | ||
| 224 | "Tried to free nvmap handle: {} but didn't as it still has duplicates", | ||
| 225 | handle); | ||
| 226 | |||
| 227 | freeInfo = { | ||
| 228 | .address = handleDesc->address, | ||
| 229 | .size = handleDesc->size, | ||
| 230 | .was_uncached = handleDesc->flags.map_uncached.Value() != 0, | ||
| 231 | }; | ||
| 232 | } else { | ||
| 233 | return std::nullopt; | ||
| 234 | } | ||
| 235 | |||
| 236 | // Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed | ||
| 237 | if (!hWeak.expired()) { | ||
| 238 | LOG_ERROR(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle); | ||
| 239 | freeInfo.address = 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | return freeInfo; | ||
| 243 | } | ||
| 244 | |||
| 245 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h new file mode 100644 index 000000000..e47aa755d --- /dev/null +++ b/src/core/hle/service/nvdrv/core/nvmap.h | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | // Copyright 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <list> | ||
| 8 | #include <memory> | ||
| 9 | #include <mutex> | ||
| 10 | #include <optional> | ||
| 11 | #include <unordered_map> | ||
| 12 | #include <assert.h> | ||
| 13 | |||
| 14 | #include "common/bit_field.h" | ||
| 15 | #include "common/common_types.h" | ||
| 16 | #include "core/hle/service/nvdrv/nvdata.h" | ||
| 17 | |||
| 18 | namespace Service::Nvidia::NvCore { | ||
| 19 | /** | ||
| 20 | * @brief The nvmap core class holds the global state for nvmap and provides methods to manage | ||
| 21 | * handles | ||
| 22 | */ | ||
| 23 | class NvMap { | ||
| 24 | public: | ||
| 25 | /** | ||
| 26 | * @brief A handle to a contiguous block of memory in an application's address space | ||
| 27 | */ | ||
| 28 | struct Handle { | ||
| 29 | std::mutex mutex; | ||
| 30 | |||
| 31 | u64 align{}; //!< The alignment to use when pinning the handle onto the SMMU | ||
| 32 | u64 size; //!< Page-aligned size of the memory the handle refers to | ||
| 33 | u64 aligned_size; //!< `align`-aligned size of the memory the handle refers to | ||
| 34 | u64 orig_size; //!< Original unaligned size of the memory this handle refers to | ||
| 35 | |||
| 36 | s32 dupes{1}; //!< How many guest references there are to this handle | ||
| 37 | s32 internal_dupes{0}; //!< How many emulator-internal references there are to this handle | ||
| 38 | |||
| 39 | using Id = u32; | ||
| 40 | Id id; //!< A globally unique identifier for this handle | ||
| 41 | |||
| 42 | s32 pins{}; | ||
| 43 | u32 pin_virt_address{}; | ||
| 44 | std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{}; | ||
| 45 | |||
| 46 | union Flags { | ||
| 47 | BitField<0, 1, u32> map_uncached; //!< If the handle should be mapped as uncached | ||
| 48 | BitField<2, 1, u32> keep_uncached_after_free; //!< Only applicable when the handle was | ||
| 49 | //!< allocated with a fixed address | ||
| 50 | BitField<4, 1, u32> _unk0_; //!< Passed to IOVMM for pins | ||
| 51 | } flags{}; | ||
| 52 | static_assert(sizeof(Flags) == sizeof(u32)); | ||
| 53 | |||
| 54 | u64 address{}; //!< The memory location in the guest's AS that this handle corresponds to, | ||
| 55 | //!< this can also be in the nvdrv tmem | ||
| 56 | bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC | ||
| 57 | //!< call | ||
| 58 | |||
| 59 | u8 kind{}; //!< Used for memory compression | ||
| 60 | bool allocated{}; //!< If the handle has been allocated with `Alloc` | ||
| 61 | |||
| 62 | Handle(u64 size, Id id); | ||
| 63 | |||
| 64 | /** | ||
| 65 | * @brief Sets up the handle with the given memory config, can allocate memory from the tmem | ||
| 66 | * if a 0 address is passed | ||
| 67 | */ | ||
| 68 | [[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * @brief Increases the dupe counter of the handle for the given session | ||
| 72 | */ | ||
| 73 | [[nodiscard]] NvResult Duplicate(bool internal_session); | ||
| 74 | |||
| 75 | /** | ||
| 76 | * @brief Obtains a pointer to the handle's memory and marks the handle it as having been | ||
| 77 | * mapped | ||
| 78 | */ | ||
| 79 | u8* GetPointer() { | ||
| 80 | if (!address) { | ||
| 81 | return nullptr; | ||
| 82 | } | ||
| 83 | |||
| 84 | is_shared_mem_mapped = true; | ||
| 85 | return reinterpret_cast<u8*>(address); | ||
| 86 | } | ||
| 87 | }; | ||
| 88 | |||
| 89 | private: | ||
| 90 | std::list<std::shared_ptr<Handle>> unmap_queue; | ||
| 91 | std::mutex unmap_queue_lock; //!< Protects access to `unmap_queue` | ||
| 92 | |||
| 93 | std::unordered_map<Handle::Id, std::shared_ptr<Handle>> handles; //!< Main owning map of handles | ||
| 94 | std::mutex handles_lock; //!< Protects access to `handles` | ||
| 95 | |||
| 96 | static constexpr u32 HandleIdIncrement{ | ||
| 97 | 4}; //!< Each new handle ID is an increment of 4 from the previous | ||
| 98 | std::atomic<u32> next_handle_id{HandleIdIncrement}; | ||
| 99 | |||
| 100 | void AddHandle(std::shared_ptr<Handle> handle); | ||
| 101 | |||
| 102 | /** | ||
| 103 | * @brief Unmaps and frees the SMMU memory region a handle is mapped to | ||
| 104 | * @note Both `unmap_queue_lock` and `handleDesc.mutex` MUST be locked when calling this | ||
| 105 | */ | ||
| 106 | void UnmapHandle(Handle& handleDesc); | ||
| 107 | |||
| 108 | /** | ||
| 109 | * @brief Removes a handle from the map taking its dupes into account | ||
| 110 | * @note handleDesc.mutex MUST be locked when calling this | ||
| 111 | * @return If the handle was removed from the map | ||
| 112 | */ | ||
| 113 | bool TryRemoveHandle(const Handle& handleDesc); | ||
| 114 | |||
| 115 | public: | ||
| 116 | /** | ||
| 117 | * @brief Encapsulates the result of a FreeHandle operation | ||
| 118 | */ | ||
| 119 | struct FreeInfo { | ||
| 120 | u64 address; //!< Address the handle referred to before deletion | ||
| 121 | u64 size; //!< Page-aligned handle size | ||
| 122 | bool was_uncached; //!< If the handle was allocated as uncached | ||
| 123 | }; | ||
| 124 | |||
| 125 | NvMap(); | ||
| 126 | |||
| 127 | /** | ||
| 128 | * @brief Creates an unallocated handle of the given size | ||
| 129 | */ | ||
| 130 | [[nodiscard]] NvResult CreateHandle(u64 size, std::shared_ptr<NvMap::Handle>& result_out); | ||
| 131 | |||
| 132 | std::shared_ptr<Handle> GetHandle(Handle::Id handle); | ||
| 133 | |||
| 134 | /** | ||
| 135 | * @brief Maps a handle into the SMMU address space | ||
| 136 | * @note This operation is refcounted, the number of calls to this must eventually match the | ||
| 137 | * number of calls to `UnpinHandle` | ||
| 138 | * @return The SMMU virtual address that the handle has been mapped to | ||
| 139 | */ | ||
| 140 | u32 PinHandle(Handle::Id handle); | ||
| 141 | |||
| 142 | /** | ||
| 143 | * @brief When this has been called an equal number of times to `PinHandle` for the supplied | ||
| 144 | * handle it will be added to a list of handles to be freed when necessary | ||
| 145 | */ | ||
| 146 | void UnpinHandle(Handle::Id handle); | ||
| 147 | |||
| 148 | /** | ||
| 149 | * @brief Tries to free a handle and remove a single dupe | ||
| 150 | * @note If a handle has no dupes left and has no other users a FreeInfo struct will be returned | ||
| 151 | * describing the prior state of the handle | ||
| 152 | */ | ||
| 153 | std::optional<FreeInfo> FreeHandle(Handle::Id handle, bool internal_session); | ||
| 154 | }; | ||
| 155 | } // namespace Service::Nvidia::NvCore | ||
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp index a6fa943e8..ff6cbb37e 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp | |||
| @@ -2,10 +2,10 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/assert.h" | 4 | #include "common/assert.h" |
| 5 | #include "core/hle/service/nvdrv/syncpoint_manager.h" | 5 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" |
| 6 | #include "video_core/gpu.h" | 6 | #include "video_core/gpu.h" |
| 7 | 7 | ||
| 8 | namespace Service::Nvidia { | 8 | namespace Service::Nvidia::NvCore { |
| 9 | 9 | ||
| 10 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {} | 10 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {} |
| 11 | 11 | ||
| @@ -35,4 +35,4 @@ u32 SyncpointManager::IncreaseSyncpoint(u32 syncpoint_id, u32 value) { | |||
| 35 | return GetSyncpointMax(syncpoint_id); | 35 | return GetSyncpointMax(syncpoint_id); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | } // namespace Service::Nvidia | 38 | } // namespace Service::Nvidia::NvCore |
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.h b/src/core/hle/service/nvdrv/core/syncpoint_manager.h index 7f080f76e..cf7f0b4be 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.h | |||
| @@ -13,7 +13,7 @@ namespace Tegra { | |||
| 13 | class GPU; | 13 | class GPU; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace Service::Nvidia { | 16 | namespace Service::Nvidia::NvCore { |
| 17 | 17 | ||
| 18 | class SyncpointManager final { | 18 | class SyncpointManager final { |
| 19 | public: | 19 | public: |
| @@ -81,4 +81,4 @@ private: | |||
| 81 | Tegra::GPU& gpu; | 81 | Tegra::GPU& gpu; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | } // namespace Service::Nvidia | 84 | } // namespace Service::Nvidia::NvCore |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp index 55acd4f78..5e2155e6c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp | |||
| @@ -12,15 +12,17 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/hle/kernel/k_event.h" | 13 | #include "core/hle/kernel/k_event.h" |
| 14 | #include "core/hle/kernel/k_writable_event.h" | 14 | #include "core/hle/kernel/k_writable_event.h" |
| 15 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 16 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||
| 15 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" | 17 | #include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" |
| 16 | #include "video_core/gpu.h" | 18 | #include "video_core/gpu.h" |
| 17 | 19 | ||
| 18 | namespace Service::Nvidia::Devices { | 20 | namespace Service::Nvidia::Devices { |
| 19 | 21 | ||
| 20 | nvhost_ctrl::nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, | 22 | nvhost_ctrl::nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, |
| 21 | SyncpointManager& syncpoint_manager_) | 23 | NvCore::Container& core_) |
| 22 | : nvdevice{system_}, events_interface{events_interface_}, syncpoint_manager{ | 24 | : nvdevice{system_}, events_interface{events_interface_}, core{core_}, |
| 23 | syncpoint_manager_} {} | 25 | syncpoint_manager{core_.GetSyncpointManager()} {} |
| 24 | nvhost_ctrl::~nvhost_ctrl() = default; | 26 | nvhost_ctrl::~nvhost_ctrl() = default; |
| 25 | 27 | ||
| 26 | NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 28 | NvResult nvhost_ctrl::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h index d548a7827..9fd46ea5f 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h | |||
| @@ -10,12 +10,17 @@ | |||
| 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 10 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 11 | #include "core/hle/service/nvdrv/nvdrv.h" | 11 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 12 | 12 | ||
| 13 | namespace Service::Nvidia::NvCore { | ||
| 14 | class Container; | ||
| 15 | class SyncpointManager; | ||
| 16 | } // namespace Service::Nvidia::NvCore | ||
| 17 | |||
| 13 | namespace Service::Nvidia::Devices { | 18 | namespace Service::Nvidia::Devices { |
| 14 | 19 | ||
| 15 | class nvhost_ctrl final : public nvdevice { | 20 | class nvhost_ctrl final : public nvdevice { |
| 16 | public: | 21 | public: |
| 17 | explicit nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, | 22 | explicit nvhost_ctrl(Core::System& system_, EventInterface& events_interface_, |
| 18 | SyncpointManager& syncpoint_manager_); | 23 | NvCore::Container& core); |
| 19 | ~nvhost_ctrl() override; | 24 | ~nvhost_ctrl() override; |
| 20 | 25 | ||
| 21 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 26 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| @@ -145,7 +150,8 @@ private: | |||
| 145 | NvResult FreeEvent(u32 slot); | 150 | NvResult FreeEvent(u32 slot); |
| 146 | 151 | ||
| 147 | EventInterface& events_interface; | 152 | EventInterface& events_interface; |
| 148 | SyncpointManager& syncpoint_manager; | 153 | NvCore::Container& core; |
| 154 | NvCore::SyncpointManager& syncpoint_manager; | ||
| 149 | }; | 155 | }; |
| 150 | 156 | ||
| 151 | } // namespace Service::Nvidia::Devices | 157 | } // namespace Service::Nvidia::Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index e87fa5992..a480bfc47 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
| @@ -5,9 +5,10 @@ | |||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 9 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||
| 8 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" | 10 | #include "core/hle/service/nvdrv/devices/nvhost_gpu.h" |
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | 11 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 10 | #include "core/hle/service/nvdrv/syncpoint_manager.h" | ||
| 11 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 12 | #include "video_core/gpu.h" | 13 | #include "video_core/gpu.h" |
| 13 | 14 | ||
| @@ -22,10 +23,10 @@ Tegra::CommandHeader BuildFenceAction(Tegra::GPU::FenceOperation op, u32 syncpoi | |||
| 22 | } // namespace | 23 | } // namespace |
| 23 | 24 | ||
| 24 | nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 25 | nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 25 | EventInterface& events_interface_, SyncpointManager& syncpoint_manager_) | 26 | EventInterface& events_interface_, NvCore::Container& core_) |
| 26 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, events_interface{events_interface_}, | 27 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, events_interface{events_interface_}, |
| 27 | syncpoint_manager{syncpoint_manager_} { | 28 | core{core_}, syncpoint_manager{core_.GetSyncpointManager()} { |
| 28 | channel_fence.id = syncpoint_manager_.AllocateSyncpoint(); | 29 | channel_fence.id = syncpoint_manager.AllocateSyncpoint(); |
| 29 | channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id); | 30 | channel_fence.value = system_.GPU().GetSyncpointValue(channel_fence.id); |
| 30 | sm_exception_breakpoint_int_report_event = | 31 | sm_exception_breakpoint_int_report_event = |
| 31 | events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointInt"); | 32 | events_interface.CreateNonCtrlEvent("GpuChannelSMExceptionBreakpointInt"); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index eb4936df0..4f73a7bae 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h | |||
| @@ -14,7 +14,12 @@ | |||
| 14 | #include "video_core/dma_pusher.h" | 14 | #include "video_core/dma_pusher.h" |
| 15 | 15 | ||
| 16 | namespace Service::Nvidia { | 16 | namespace Service::Nvidia { |
| 17 | |||
| 18 | namespace NvCore { | ||
| 19 | class Container; | ||
| 17 | class SyncpointManager; | 20 | class SyncpointManager; |
| 21 | } // namespace NvCore | ||
| 22 | |||
| 18 | class EventInterface; | 23 | class EventInterface; |
| 19 | } // namespace Service::Nvidia | 24 | } // namespace Service::Nvidia |
| 20 | 25 | ||
| @@ -24,7 +29,7 @@ class nvmap; | |||
| 24 | class nvhost_gpu final : public nvdevice { | 29 | class nvhost_gpu final : public nvdevice { |
| 25 | public: | 30 | public: |
| 26 | explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 31 | explicit nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 27 | EventInterface& events_interface_, SyncpointManager& syncpoint_manager_); | 32 | EventInterface& events_interface_, NvCore::Container& core); |
| 28 | ~nvhost_gpu() override; | 33 | ~nvhost_gpu() override; |
| 29 | 34 | ||
| 30 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 35 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
| @@ -196,7 +201,8 @@ private: | |||
| 196 | 201 | ||
| 197 | std::shared_ptr<nvmap> nvmap_dev; | 202 | std::shared_ptr<nvmap> nvmap_dev; |
| 198 | EventInterface& events_interface; | 203 | EventInterface& events_interface; |
| 199 | SyncpointManager& syncpoint_manager; | 204 | NvCore::Container& core; |
| 205 | NvCore::SyncpointManager& syncpoint_manager; | ||
| 200 | NvFence channel_fence; | 206 | NvFence channel_fence; |
| 201 | 207 | ||
| 202 | // Events | 208 | // Events |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index a7385fce8..2c9158c7c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp | |||
| @@ -11,8 +11,8 @@ | |||
| 11 | namespace Service::Nvidia::Devices { | 11 | namespace Service::Nvidia::Devices { |
| 12 | 12 | ||
| 13 | nvhost_nvdec::nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 13 | nvhost_nvdec::nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 14 | SyncpointManager& syncpoint_manager_) | 14 | NvCore::Container& core) |
| 15 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {} | 15 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), core} {} |
| 16 | nvhost_nvdec::~nvhost_nvdec() = default; | 16 | nvhost_nvdec::~nvhost_nvdec() = default; |
| 17 | 17 | ||
| 18 | NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 18 | NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h index 29b3e6a36..04da4a913 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h | |||
| @@ -11,7 +11,7 @@ namespace Service::Nvidia::Devices { | |||
| 11 | class nvhost_nvdec final : public nvhost_nvdec_common { | 11 | class nvhost_nvdec final : public nvhost_nvdec_common { |
| 12 | public: | 12 | public: |
| 13 | explicit nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 13 | explicit nvhost_nvdec(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 14 | SyncpointManager& syncpoint_manager_); | 14 | NvCore::Container& core); |
| 15 | ~nvhost_nvdec() override; | 15 | ~nvhost_nvdec() override; |
| 16 | 16 | ||
| 17 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 17 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp index 8b2cd9bf1..5a9c59f37 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp | |||
| @@ -8,9 +8,10 @@ | |||
| 8 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 12 | #include "core/hle/service/nvdrv/core/syncpoint_manager.h" | ||
| 11 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h" | 13 | #include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h" |
| 12 | #include "core/hle/service/nvdrv/devices/nvmap.h" | 14 | #include "core/hle/service/nvdrv/devices/nvmap.h" |
| 13 | #include "core/hle/service/nvdrv/syncpoint_manager.h" | ||
| 14 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 15 | #include "video_core/memory_manager.h" | 16 | #include "video_core/memory_manager.h" |
| 16 | #include "video_core/renderer_base.h" | 17 | #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 | |||
| 45 | } // Anonymous namespace | 46 | } // Anonymous namespace |
| 46 | 47 | ||
| 47 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 48 | nvhost_nvdec_common::nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 48 | SyncpointManager& syncpoint_manager_) | 49 | NvCore::Container& core_) |
| 49 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, syncpoint_manager{syncpoint_manager_} {} | 50 | : nvdevice{system_}, nvmap_dev{std::move(nvmap_dev_)}, core{core_}, |
| 51 | syncpoint_manager{core.GetSyncpointManager()} {} | ||
| 50 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; | 52 | nvhost_nvdec_common::~nvhost_nvdec_common() = default; |
| 51 | 53 | ||
| 52 | NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { | 54 | NvResult nvhost_nvdec_common::SetNVMAPfd(const std::vector<u8>& input) { |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 12d39946d..cccc94a58 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -9,7 +9,11 @@ | |||
| 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 9 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 10 | 10 | ||
| 11 | namespace Service::Nvidia { | 11 | namespace Service::Nvidia { |
| 12 | |||
| 13 | namespace NvCore { | ||
| 12 | class SyncpointManager; | 14 | class SyncpointManager; |
| 15 | class Container; | ||
| 16 | } // namespace NvCore | ||
| 13 | 17 | ||
| 14 | namespace Devices { | 18 | namespace Devices { |
| 15 | class nvmap; | 19 | class nvmap; |
| @@ -17,7 +21,7 @@ class nvmap; | |||
| 17 | class nvhost_nvdec_common : public nvdevice { | 21 | class nvhost_nvdec_common : public nvdevice { |
| 18 | public: | 22 | public: |
| 19 | explicit nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 23 | explicit nvhost_nvdec_common(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 20 | SyncpointManager& syncpoint_manager_); | 24 | NvCore::Container& core); |
| 21 | ~nvhost_nvdec_common() override; | 25 | ~nvhost_nvdec_common() override; |
| 22 | 26 | ||
| 23 | protected: | 27 | protected: |
| @@ -114,7 +118,8 @@ protected: | |||
| 114 | s32_le nvmap_fd{}; | 118 | s32_le nvmap_fd{}; |
| 115 | u32_le submit_timeout{}; | 119 | u32_le submit_timeout{}; |
| 116 | std::shared_ptr<nvmap> nvmap_dev; | 120 | std::shared_ptr<nvmap> nvmap_dev; |
| 117 | SyncpointManager& syncpoint_manager; | 121 | NvCore::Container& core; |
| 122 | NvCore::SyncpointManager& syncpoint_manager; | ||
| 118 | std::array<u32, MaxSyncPoints> device_syncpoints{}; | 123 | std::array<u32, MaxSyncPoints> device_syncpoints{}; |
| 119 | }; | 124 | }; |
| 120 | }; // namespace Devices | 125 | }; // namespace Devices |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index f58e8bada..66558c331 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | namespace Service::Nvidia::Devices { | 10 | namespace Service::Nvidia::Devices { |
| 11 | nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 11 | nvhost_vic::nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 12 | SyncpointManager& syncpoint_manager_) | 12 | NvCore::Container& core) |
| 13 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), syncpoint_manager_} {} | 13 | : nvhost_nvdec_common{system_, std::move(nvmap_dev_), core} {} |
| 14 | 14 | ||
| 15 | nvhost_vic::~nvhost_vic() = default; | 15 | nvhost_vic::~nvhost_vic() = default; |
| 16 | 16 | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h index b41b195ae..6f9838b2d 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h | |||
| @@ -10,7 +10,7 @@ namespace Service::Nvidia::Devices { | |||
| 10 | class nvhost_vic final : public nvhost_nvdec_common { | 10 | class nvhost_vic final : public nvhost_nvdec_common { |
| 11 | public: | 11 | public: |
| 12 | explicit nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, | 12 | explicit nvhost_vic(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_, |
| 13 | SyncpointManager& syncpoint_manager_); | 13 | NvCore::Container& core); |
| 14 | ~nvhost_vic(); | 14 | ~nvhost_vic(); |
| 15 | 15 | ||
| 16 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, | 16 | NvResult Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& input, |
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index df4656240..824c0e290 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/hle/ipc_helpers.h" | 11 | #include "core/hle/ipc_helpers.h" |
| 12 | #include "core/hle/kernel/k_event.h" | 12 | #include "core/hle/kernel/k_event.h" |
| 13 | #include "core/hle/kernel/k_writable_event.h" | 13 | #include "core/hle/kernel/k_writable_event.h" |
| 14 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 14 | #include "core/hle/service/nvdrv/devices/nvdevice.h" | 15 | #include "core/hle/service/nvdrv/devices/nvdevice.h" |
| 15 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 16 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| 16 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | 17 | #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" |
| @@ -24,8 +25,8 @@ | |||
| 24 | #include "core/hle/service/nvdrv/nvdrv.h" | 25 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 25 | #include "core/hle/service/nvdrv/nvdrv_interface.h" | 26 | #include "core/hle/service/nvdrv/nvdrv_interface.h" |
| 26 | #include "core/hle/service/nvdrv/nvmemp.h" | 27 | #include "core/hle/service/nvdrv/nvmemp.h" |
| 27 | #include "core/hle/service/nvdrv/syncpoint_manager.h" | ||
| 28 | #include "core/hle/service/nvflinger/nvflinger.h" | 28 | #include "core/hle/service/nvflinger/nvflinger.h" |
| 29 | #include "video_core/gpu.h" | ||
| 29 | 30 | ||
| 30 | namespace Service::Nvidia { | 31 | namespace Service::Nvidia { |
| 31 | 32 | ||
| @@ -75,6 +76,7 @@ void EventInterface::Create(u32 event_id) { | |||
| 75 | const u64 mask = 1ULL << event_id; | 76 | const u64 mask = 1ULL << event_id; |
| 76 | fails[event_id] = 0; | 77 | fails[event_id] = 0; |
| 77 | events_mask |= mask; | 78 | events_mask |= mask; |
| 79 | assigned_syncpt[event_id] = 0; | ||
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | void EventInterface::Free(u32 event_id) { | 82 | void EventInterface::Free(u32 event_id) { |
| @@ -135,22 +137,22 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger | |||
| 135 | } | 137 | } |
| 136 | 138 | ||
| 137 | Module::Module(Core::System& system) | 139 | Module::Module(Core::System& system) |
| 138 | : syncpoint_manager{system.GPU()}, service_context{system, "nvdrv"}, events_interface{*this} { | 140 | : service_context{system, "nvdrv"}, events_interface{*this}, container{system.GPU()} { |
| 139 | auto nvmap_dev = std::make_shared<Devices::nvmap>(system); | 141 | auto nvmap_dev = std::make_shared<Devices::nvmap>(system); |
| 140 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); | 142 | devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(system, nvmap_dev); |
| 141 | devices["/dev/nvhost-gpu"] = std::make_shared<Devices::nvhost_gpu>( | 143 | devices["/dev/nvhost-gpu"] = |
| 142 | system, nvmap_dev, events_interface, syncpoint_manager); | 144 | std::make_shared<Devices::nvhost_gpu>(system, nvmap_dev, events_interface, container); |
| 143 | devices["/dev/nvhost-ctrl-gpu"] = | 145 | devices["/dev/nvhost-ctrl-gpu"] = |
| 144 | std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); | 146 | std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); |
| 145 | devices["/dev/nvmap"] = nvmap_dev; | 147 | devices["/dev/nvmap"] = nvmap_dev; |
| 146 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev); | 148 | devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(system, nvmap_dev); |
| 147 | devices["/dev/nvhost-ctrl"] = | 149 | devices["/dev/nvhost-ctrl"] = |
| 148 | std::make_shared<Devices::nvhost_ctrl>(system, events_interface, syncpoint_manager); | 150 | std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container); |
| 149 | devices["/dev/nvhost-nvdec"] = | 151 | devices["/dev/nvhost-nvdec"] = |
| 150 | std::make_shared<Devices::nvhost_nvdec>(system, nvmap_dev, syncpoint_manager); | 152 | std::make_shared<Devices::nvhost_nvdec>(system, nvmap_dev, container); |
| 151 | devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system); | 153 | devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>(system); |
| 152 | devices["/dev/nvhost-vic"] = | 154 | devices["/dev/nvhost-vic"] = |
| 153 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, syncpoint_manager); | 155 | std::make_shared<Devices::nvhost_vic>(system, nvmap_dev, container); |
| 154 | } | 156 | } |
| 155 | 157 | ||
| 156 | Module::~Module() = default; | 158 | Module::~Module() = default; |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index d24b57539..96adf2ffb 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "core/hle/service/kernel_helpers.h" | 14 | #include "core/hle/service/kernel_helpers.h" |
| 15 | #include "core/hle/service/nvdrv/core/container.h" | ||
| 15 | #include "core/hle/service/nvdrv/nvdata.h" | 16 | #include "core/hle/service/nvdrv/nvdata.h" |
| 16 | #include "core/hle/service/nvdrv/syncpoint_manager.h" | ||
| 17 | #include "core/hle/service/nvflinger/ui/fence.h" | 17 | #include "core/hle/service/nvflinger/ui/fence.h" |
| 18 | #include "core/hle/service/service.h" | 18 | #include "core/hle/service/service.h" |
| 19 | 19 | ||
| @@ -31,7 +31,10 @@ class NVFlinger; | |||
| 31 | 31 | ||
| 32 | namespace Service::Nvidia { | 32 | namespace Service::Nvidia { |
| 33 | 33 | ||
| 34 | namespace NvCore { | ||
| 35 | class Container; | ||
| 34 | class SyncpointManager; | 36 | class SyncpointManager; |
| 37 | } // namespace NvCore | ||
| 35 | 38 | ||
| 36 | namespace Devices { | 39 | namespace Devices { |
| 37 | class nvdevice; | 40 | class nvdevice; |
| @@ -126,9 +129,6 @@ public: | |||
| 126 | private: | 129 | private: |
| 127 | friend class EventInterface; | 130 | friend class EventInterface; |
| 128 | 131 | ||
| 129 | /// Manages syncpoints on the host | ||
| 130 | SyncpointManager syncpoint_manager; | ||
| 131 | |||
| 132 | /// Id to use for the next open file descriptor. | 132 | /// Id to use for the next open file descriptor. |
| 133 | DeviceFD next_fd = 1; | 133 | DeviceFD next_fd = 1; |
| 134 | 134 | ||
| @@ -142,6 +142,9 @@ private: | |||
| 142 | 142 | ||
| 143 | EventInterface events_interface; | 143 | EventInterface events_interface; |
| 144 | 144 | ||
| 145 | /// Manages syncpoints on the host | ||
| 146 | NvCore::Container container; | ||
| 147 | |||
| 145 | void CreateEvent(u32 event_id); | 148 | void CreateEvent(u32 event_id); |
| 146 | void FreeEvent(u32 event_id); | 149 | void FreeEvent(u32 event_id); |
| 147 | }; | 150 | }; |