early-access version 2790

This commit is contained in:
pineappleEA
2022-06-16 03:46:18 +02:00
parent a67a0e1eb5
commit 518fdfccad
155 changed files with 9311 additions and 2805 deletions

View File

@@ -1,16 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2021 yuzu emulator team and Skyline Team and Contributors
// (https://github.com/skyline-emu/)
// SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3
// or any later version Refer to the license.txt file included.
#pragma once
#include <functional>
#include <list>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "common/common_types.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/syncpoint_manager.h"
#include "core/hle/service/nvflinger/ui/fence.h"
#include "core/hle/service/service.h"
@@ -28,81 +33,31 @@ class NVFlinger;
namespace Service::Nvidia {
namespace NvCore {
class Container;
class SyncpointManager;
} // namespace NvCore
namespace Devices {
class nvdevice;
}
class nvhost_ctrl;
} // namespace Devices
/// Represents an Nvidia event
struct NvEvent {
Kernel::KEvent* event{};
NvFence fence{};
};
class Module;
struct EventInterface {
// Mask representing currently busy events
u64 events_mask{};
// Each kernel event associated to an NV event
std::array<NvEvent, MaxNvEvents> events;
// The status of the current NVEvent
std::array<EventState, MaxNvEvents> status{};
// Tells if an NVEvent is registered or not
std::array<bool, MaxNvEvents> registered{};
// Tells the NVEvent that it has failed.
std::array<bool, MaxNvEvents> failed{};
// When an NVEvent is waiting on GPU interrupt, this is the sync_point
// associated with it.
std::array<u32, MaxNvEvents> assigned_syncpt{};
// This is the value of the GPU interrupt for which the NVEvent is waiting
// for.
std::array<u32, MaxNvEvents> assigned_value{};
// Constant to denote an unasigned syncpoint.
static constexpr u32 unassigned_syncpt = 0xFFFFFFFF;
std::optional<u32> GetFreeEvent() const {
u64 mask = events_mask;
for (u32 i = 0; i < MaxNvEvents; i++) {
const bool is_free = (mask & 0x1) == 0;
if (is_free) {
if (status[i] == EventState::Registered || status[i] == EventState::Free) {
return {i};
}
}
mask = mask >> 1;
}
return std::nullopt;
}
void SetEventStatus(const u32 event_id, EventState new_status) {
EventState old_status = status[event_id];
if (old_status == new_status) {
return;
}
status[event_id] = new_status;
if (new_status == EventState::Registered) {
registered[event_id] = true;
}
if (new_status == EventState::Waiting || new_status == EventState::Busy) {
events_mask |= (1ULL << event_id);
}
}
void RegisterEvent(const u32 event_id) {
registered[event_id] = true;
if (status[event_id] == EventState::Free) {
status[event_id] = EventState::Registered;
}
}
void UnregisterEvent(const u32 event_id) {
registered[event_id] = false;
if (status[event_id] == EventState::Registered) {
status[event_id] = EventState::Free;
}
}
void LiberateEvent(const u32 event_id) {
status[event_id] = registered[event_id] ? EventState::Registered : EventState::Free;
events_mask &= ~(1ULL << event_id);
assigned_syncpt[event_id] = unassigned_syncpt;
assigned_value[event_id] = 0;
}
class EventInterface {
public:
EventInterface(Module& module_);
~EventInterface();
Kernel::KEvent* CreateEvent(std::string name);
void FreeEvent(Kernel::KEvent* event);
private:
Module& module;
std::mutex guard;
std::list<Devices::nvhost_ctrl*> on_signal;
};
class Module final {
@@ -112,9 +67,9 @@ public:
/// Returns a pointer to one of the available devices, identified by its name.
template <typename T>
std::shared_ptr<T> GetDevice(const std::string& name) {
auto itr = devices.find(name);
if (itr == devices.end())
std::shared_ptr<T> GetDevice(DeviceFD fd) {
auto itr = open_files.find(fd);
if (itr == open_files.end())
return nullptr;
return std::static_pointer_cast<T>(itr->second);
}
@@ -137,28 +92,28 @@ public:
/// Closes a device file descriptor and returns operation success.
NvResult Close(DeviceFD fd);
void SignalSyncpt(const u32 syncpoint_id, const u32 value);
Kernel::KReadableEvent& GetEvent(u32 event_id);
Kernel::KWritableEvent& GetEventWriteable(u32 event_id);
NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event);
private:
/// Manages syncpoints on the host
SyncpointManager syncpoint_manager;
friend class EventInterface;
/// Id to use for the next open file descriptor.
DeviceFD next_fd = 1;
using FilesContainerType = std::unordered_map<DeviceFD, std::shared_ptr<Devices::nvdevice>>;
/// Mapping of file descriptors to the devices they reference.
std::unordered_map<DeviceFD, std::shared_ptr<Devices::nvdevice>> open_files;
FilesContainerType open_files;
/// Mapping of device node names to their implementation.
std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices;
KernelHelpers::ServiceContext service_context;
EventInterface events_interface;
KernelHelpers::ServiceContext service_context;
/// Manages syncpoints on the host
NvCore::Container container;
void CreateEvent(u32 event_id);
void FreeEvent(u32 event_id);
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
};
/// Registers all NVDRV services with the specified service manager.