mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 20:39:20 +01:00
Implement the host side of host1x syncpoints
This will be extended in the future to support interfacing with the GPU.
This commit is contained in:
parent
3c5cc33a34
commit
8dc9a10324
@ -105,6 +105,7 @@ add_library(skyline SHARED
|
||||
${source_DIR}/skyline/services/nvdrv/devices/nvhost_ctrl.cpp
|
||||
${source_DIR}/skyline/services/nvdrv/devices/nvhost_channel.cpp
|
||||
${source_DIR}/skyline/services/nvdrv/devices/nvhost_as_gpu.cpp
|
||||
${source_DIR}/skyline/services/nvdrv/devices/nvhost_syncpoint.cpp
|
||||
${source_DIR}/skyline/services/hosbinder/IHOSBinderDriver.cpp
|
||||
${source_DIR}/skyline/services/visrv/IDisplayService.cpp
|
||||
${source_DIR}/skyline/services/visrv/IApplicationDisplayService.cpp
|
||||
|
@ -54,7 +54,7 @@ namespace skyline::service::nvdrv {
|
||||
return fdIndex++;
|
||||
}
|
||||
|
||||
INvDrvServices::INvDrvServices(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager, Service::nvdrv_INvDrvServices, "INvDrvServices", {
|
||||
INvDrvServices::INvDrvServices(const DeviceState &state, ServiceManager &manager) : hostSyncpoint(state), BaseService(state, manager, Service::nvdrv_INvDrvServices, "INvDrvServices", {
|
||||
{0x0, SFUNC(INvDrvServices::Open)},
|
||||
{0x1, SFUNC(INvDrvServices::Ioctl)},
|
||||
{0x2, SFUNC(INvDrvServices::Close)},
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <kernel/types/KTransferMemory.h>
|
||||
#include <gpu.h>
|
||||
#include "devices/nvdevice.h"
|
||||
#include "devices/nvhost_syncpoint.h"
|
||||
|
||||
namespace skyline::service::nvdrv {
|
||||
/**
|
||||
@ -43,6 +44,8 @@ namespace skyline::service::nvdrv {
|
||||
}
|
||||
|
||||
public:
|
||||
NvHostSyncpoint hostSyncpoint;
|
||||
|
||||
/**
|
||||
* @brief Returns a particular device with a specific type
|
||||
* @tparam objectClass The class of the device to return
|
||||
|
25
app/src/main/cpp/skyline/services/nvdrv/devices/nvfence.h
Normal file
25
app/src/main/cpp/skyline/services/nvdrv/devices/nvfence.h
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
#include "nvhost_syncpoint.h"
|
||||
|
||||
namespace skyline::service::nvdrv::device {
|
||||
/**
|
||||
* @brief This holds information about a fence
|
||||
*/
|
||||
struct NvFence {
|
||||
u32 id{};
|
||||
u32 value{};
|
||||
|
||||
/**
|
||||
* @brief Synchronizes the fence's value with its underlying syncpoint
|
||||
*/
|
||||
static inline void UpdateValue(const NvHostSyncpoint &hostSyncpoint) {
|
||||
//TODO: Implement this
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(NvFence) == 0x8);
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#include "nvhost_syncpoint.h"
|
||||
|
||||
namespace skyline::service::nvdrv {
|
||||
NvHostSyncpoint::NvHostSyncpoint(const DeviceState &state) : state(state) {
|
||||
constexpr u32 VBlank0SyncpointId{26};
|
||||
constexpr u32 VBlank1SyncpointId{27};
|
||||
|
||||
// Reserve both vblank syncpoints as client managed since the userspace driver has direct access to them
|
||||
ReserveSyncpoint(VBlank0SyncpointId, true);
|
||||
ReserveSyncpoint(VBlank1SyncpointId, true);
|
||||
}
|
||||
|
||||
u32 NvHostSyncpoint::ReserveSyncpoint(u32 id, bool clientManaged) {
|
||||
if (id >= constant::MaxHwSyncpointCount)
|
||||
throw exception("Requested syncpoint ID is too high");
|
||||
|
||||
if (syncpoints.at(id).assigned)
|
||||
throw exception("Requested syncpoint is in use");
|
||||
|
||||
syncpoints.at(id).assigned = true;
|
||||
syncpoints.at(id).clientManaged = clientManaged;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
u32 NvHostSyncpoint::FindFreeSyncpoint() {
|
||||
for (u32 i = 0; i < constant::MaxHwSyncpointCount; i++)
|
||||
if (!syncpoints[i].assigned)
|
||||
return i;
|
||||
|
||||
throw exception("Failed to find a free syncpoint!");
|
||||
}
|
||||
|
||||
u32 NvHostSyncpoint::AllocateSyncpoint(bool clientManaged) {
|
||||
std::lock_guard lock(reservationLock);
|
||||
return ReserveSyncpoint(FindFreeSyncpoint(), clientManaged);
|
||||
}
|
||||
|
||||
bool NvHostSyncpoint::HasSyncpointExpired(u32 id, u32 threshold) {
|
||||
const SyncpointInfo &syncpoint = syncpoints.at(id);
|
||||
|
||||
if (syncpoint.clientManaged)
|
||||
return static_cast<i32>(syncpoint.counterMin - threshold) >= 0;
|
||||
else
|
||||
return (syncpoint.counterMax - threshold) >= (syncpoint.counterMin - threshold);
|
||||
}
|
||||
|
||||
u32 NvHostSyncpoint::IncrementSyncpointMaxExt(u32 id, u32 amount) {
|
||||
return syncpoints.at(id).counterMax += amount;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
#include <array>
|
||||
|
||||
namespace skyline {
|
||||
namespace constant {
|
||||
constexpr size_t MaxHwSyncpointCount = 192;
|
||||
}
|
||||
|
||||
namespace service::nvdrv {
|
||||
/**
|
||||
* @todo Implement the GPU side of this
|
||||
* @brief NvHostSyncpoint handles allocating and accessing host1x syncpoints
|
||||
* @url https://http.download.nvidia.com/tegra-public-appnotes/host1x.html
|
||||
* @url https://github.com/Jetson-TX1-AndroidTV/android_kernel_jetson_tx1_hdmi_primary/blob/jetson-tx1/drivers/video/tegra/host/nvhost_syncpt.c
|
||||
*/
|
||||
class NvHostSyncpoint {
|
||||
private:
|
||||
/**
|
||||
* @brief This holds information about a single syncpoint
|
||||
*/
|
||||
struct SyncpointInfo {
|
||||
std::atomic<u32> counterMin;
|
||||
std::atomic<u32> counterMax;
|
||||
bool clientManaged;
|
||||
bool assigned;
|
||||
};
|
||||
|
||||
const DeviceState &state;
|
||||
std::array<SyncpointInfo, skyline::constant::MaxHwSyncpointCount> syncpoints{};
|
||||
Mutex reservationLock;
|
||||
|
||||
/**
|
||||
* @note reservationLock should be locked when calling this
|
||||
*/
|
||||
u32 ReserveSyncpoint(u32 id, bool clientManaged);
|
||||
|
||||
/**
|
||||
* @return The ID of the first free syncpoint
|
||||
*/
|
||||
u32 FindFreeSyncpoint();
|
||||
|
||||
public:
|
||||
NvHostSyncpoint(const DeviceState &state);
|
||||
|
||||
/**
|
||||
* @brief Finds a free syncpoint and reserves it
|
||||
* @return The ID of the reserved syncpoint
|
||||
*/
|
||||
u32 AllocateSyncpoint(bool clientManaged);
|
||||
|
||||
/**
|
||||
* @url https://github.com/Jetson-TX1-AndroidTV/android_kernel_jetson_tx1_hdmi_primary/blob/8f74a72394efb871cb3f886a3de2998cd7ff2990/drivers/gpu/host1x/syncpt.c#L259
|
||||
*/
|
||||
bool HasSyncpointExpired(u32 id, u32 threshold);
|
||||
|
||||
/**
|
||||
* @brief Atomically increments the maximum value of a syncpoint by the given amount
|
||||
* @return The new value of the syncpoint
|
||||
*/
|
||||
u32 IncrementSyncpointMaxExt(u32 id, u32 amount);
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user