mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-23 11:55:00 +00:00
equeue: sceGnmGetEqEventType/sceKernelGetEventData impl (#1839)
This commit is contained in:
parent
e40ede5db2
commit
f95803664b
4 changed files with 51 additions and 22 deletions
|
@ -29,7 +29,7 @@ namespace Libraries::GnmDriver {
|
||||||
|
|
||||||
using namespace AmdGpu;
|
using namespace AmdGpu;
|
||||||
|
|
||||||
enum GnmEventIdents : u64 {
|
enum GnmEventType : u64 {
|
||||||
Compute0RelMem = 0x00,
|
Compute0RelMem = 0x00,
|
||||||
Compute1RelMem = 0x01,
|
Compute1RelMem = 0x01,
|
||||||
Compute2RelMem = 0x02,
|
Compute2RelMem = 0x02,
|
||||||
|
@ -337,6 +337,12 @@ static inline u32* ClearContextState(u32* cmdbuf) {
|
||||||
return cmdbuf + ClearStateSequence.size();
|
return cmdbuf + ClearStateSequence.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool IsValidEventType(Platform::InterruptId id) {
|
||||||
|
return (static_cast<u32>(id) >= static_cast<u32>(Platform::InterruptId::Compute0RelMem) &&
|
||||||
|
static_cast<u32>(id) <= static_cast<u32>(Platform::InterruptId::Compute6RelMem)) ||
|
||||||
|
static_cast<u32>(id) == static_cast<u32>(Platform::InterruptId::GfxEop);
|
||||||
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
|
s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
|
||||||
LOG_TRACE(Lib_GnmDriver, "called");
|
LOG_TRACE(Lib_GnmDriver, "called");
|
||||||
|
|
||||||
|
@ -347,8 +353,7 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
|
||||||
EqueueEvent kernel_event{};
|
EqueueEvent kernel_event{};
|
||||||
kernel_event.event.ident = id;
|
kernel_event.event.ident = id;
|
||||||
kernel_event.event.filter = SceKernelEvent::Filter::GraphicsCore;
|
kernel_event.event.filter = SceKernelEvent::Filter::GraphicsCore;
|
||||||
// The library only sets EV_ADD but it is suspected the kernel driver forces EV_CLEAR
|
kernel_event.event.flags = SceKernelEvent::Flags::Add;
|
||||||
kernel_event.event.flags = SceKernelEvent::Flags::Clear;
|
|
||||||
kernel_event.event.fflags = 0;
|
kernel_event.event.fflags = 0;
|
||||||
kernel_event.event.data = id;
|
kernel_event.event.data = id;
|
||||||
kernel_event.event.udata = udata;
|
kernel_event.event.udata = udata;
|
||||||
|
@ -357,11 +362,15 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
|
||||||
Platform::IrqC::Instance()->Register(
|
Platform::IrqC::Instance()->Register(
|
||||||
static_cast<Platform::InterruptId>(id),
|
static_cast<Platform::InterruptId>(id),
|
||||||
[=](Platform::InterruptId irq) {
|
[=](Platform::InterruptId irq) {
|
||||||
ASSERT_MSG(irq == static_cast<Platform::InterruptId>(id),
|
ASSERT_MSG(irq == static_cast<Platform::InterruptId>(id), "An unexpected IRQ occured");
|
||||||
"An unexpected IRQ occured"); // We need to convert IRQ# to event id and do
|
|
||||||
// proper filtering in trigger function
|
// We need to convert IRQ# to event id
|
||||||
eq->TriggerEvent(static_cast<GnmEventIdents>(id), SceKernelEvent::Filter::GraphicsCore,
|
if (!IsValidEventType(irq))
|
||||||
nullptr);
|
return;
|
||||||
|
|
||||||
|
// Event data is expected to be an event type as per sceGnmGetEqEventType.
|
||||||
|
eq->TriggerEvent(static_cast<GnmEventType>(id), SceKernelEvent::Filter::GraphicsCore,
|
||||||
|
reinterpret_cast<void*>(id));
|
||||||
},
|
},
|
||||||
eq);
|
eq);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -476,7 +485,7 @@ s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
eq->RemoveEvent(id);
|
eq->RemoveEvent(id, SceKernelEvent::Filter::GraphicsCore);
|
||||||
|
|
||||||
Platform::IrqC::Instance()->Unregister(static_cast<Platform::InterruptId>(id), eq);
|
Platform::IrqC::Instance()->Unregister(static_cast<Platform::InterruptId>(id), eq);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -1000,9 +1009,13 @@ int PS4_SYSV_ABI sceGnmGetDebugTimestamp() {
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmGetEqEventType() {
|
int PS4_SYSV_ABI sceGnmGetEqEventType(const SceKernelEvent* ev) {
|
||||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
LOG_TRACE(Lib_GnmDriver, "called");
|
||||||
return ORBIS_OK;
|
|
||||||
|
auto data = sceKernelGetEventData(ev);
|
||||||
|
ASSERT(static_cast<GnmEventType>(data) == GnmEventType::GfxEop);
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmGetEqTimeStamp() {
|
int PS4_SYSV_ABI sceGnmGetEqTimeStamp() {
|
||||||
|
|
|
@ -85,7 +85,7 @@ int PS4_SYSV_ABI sceGnmGetCoredumpMode();
|
||||||
int PS4_SYSV_ABI sceGnmGetCoredumpProtectionFaultTimestamp();
|
int PS4_SYSV_ABI sceGnmGetCoredumpProtectionFaultTimestamp();
|
||||||
int PS4_SYSV_ABI sceGnmGetDbgGcHandle();
|
int PS4_SYSV_ABI sceGnmGetDbgGcHandle();
|
||||||
int PS4_SYSV_ABI sceGnmGetDebugTimestamp();
|
int PS4_SYSV_ABI sceGnmGetDebugTimestamp();
|
||||||
int PS4_SYSV_ABI sceGnmGetEqEventType();
|
int PS4_SYSV_ABI sceGnmGetEqEventType(const SceKernelEvent* ev);
|
||||||
int PS4_SYSV_ABI sceGnmGetEqTimeStamp();
|
int PS4_SYSV_ABI sceGnmGetEqTimeStamp();
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuBlockStatus();
|
int PS4_SYSV_ABI sceGnmGetGpuBlockStatus();
|
||||||
u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency();
|
u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency();
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
// Events are uniquely identified by id and filter.
|
||||||
|
|
||||||
bool EqueueInternal::AddEvent(EqueueEvent& event) {
|
bool EqueueInternal::AddEvent(EqueueEvent& event) {
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
|
@ -27,12 +29,13 @@ bool EqueueInternal::AddEvent(EqueueEvent& event) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EqueueInternal::RemoveEvent(u64 id) {
|
bool EqueueInternal::RemoveEvent(u64 id, s16 filter) {
|
||||||
bool has_found = false;
|
bool has_found = false;
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
const auto& it =
|
const auto& it = std::ranges::find_if(m_events, [id, filter](auto& ev) {
|
||||||
std::ranges::find_if(m_events, [id](auto& ev) { return ev.event.ident == id; });
|
return ev.event.ident == id && ev.event.filter == filter;
|
||||||
|
});
|
||||||
if (it != m_events.cend()) {
|
if (it != m_events.cend()) {
|
||||||
m_events.erase(it);
|
m_events.erase(it);
|
||||||
has_found = true;
|
has_found = true;
|
||||||
|
@ -68,7 +71,7 @@ int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
|
||||||
|
|
||||||
if (ev->flags & SceKernelEvent::Flags::OneShot) {
|
if (ev->flags & SceKernelEvent::Flags::OneShot) {
|
||||||
for (auto ev_id = 0u; ev_id < count; ++ev_id) {
|
for (auto ev_id = 0u; ev_id < count; ++ev_id) {
|
||||||
RemoveEvent(ev->ident);
|
RemoveEvent(ev->ident, ev->filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +97,11 @@ int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (auto& event : m_events) {
|
for (auto& event : m_events) {
|
||||||
if (event.IsTriggered()) {
|
if (event.IsTriggered()) {
|
||||||
|
// Event should not trigger again
|
||||||
|
event.ResetTriggerState();
|
||||||
|
|
||||||
if (event.event.flags & SceKernelEvent::Flags::Clear) {
|
if (event.event.flags & SceKernelEvent::Flags::Clear) {
|
||||||
event.Reset();
|
event.Clear();
|
||||||
}
|
}
|
||||||
ev[count++] = event.event;
|
ev[count++] = event.event;
|
||||||
if (count == num) {
|
if (count == num) {
|
||||||
|
@ -334,7 +340,7 @@ int PS4_SYSV_ABI sceKernelDeleteUserEvent(SceKernelEqueue eq, int id) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eq->RemoveEvent(id)) {
|
if (!eq->RemoveEvent(id, SceKernelEvent::Filter::User)) {
|
||||||
return ORBIS_KERNEL_ERROR_ENOENT;
|
return ORBIS_KERNEL_ERROR_ENOENT;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -344,6 +350,10 @@ s16 PS4_SYSV_ABI sceKernelGetEventFilter(const SceKernelEvent* ev) {
|
||||||
return ev->filter;
|
return ev->filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 PS4_SYSV_ABI sceKernelGetEventData(const SceKernelEvent* ev) {
|
||||||
|
return ev->data;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) {
|
void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue);
|
LIB_FUNCTION("D0OdFMjp46I", "libkernel", 1, "libkernel", 1, 1, sceKernelCreateEqueue);
|
||||||
LIB_FUNCTION("jpFjmgAC5AE", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteEqueue);
|
LIB_FUNCTION("jpFjmgAC5AE", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteEqueue);
|
||||||
|
@ -356,6 +366,7 @@ void RegisterEventQueue(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("LJDwdSNTnDg", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteUserEvent);
|
LIB_FUNCTION("LJDwdSNTnDg", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteUserEvent);
|
||||||
LIB_FUNCTION("mJ7aghmgvfc", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventId);
|
LIB_FUNCTION("mJ7aghmgvfc", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventId);
|
||||||
LIB_FUNCTION("23CPPI1tyBY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventFilter);
|
LIB_FUNCTION("23CPPI1tyBY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventFilter);
|
||||||
|
LIB_FUNCTION("kwGyyjohI50", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventData);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
|
@ -66,8 +66,11 @@ struct EqueueEvent {
|
||||||
std::chrono::steady_clock::time_point time_added;
|
std::chrono::steady_clock::time_point time_added;
|
||||||
std::unique_ptr<boost::asio::steady_timer> timer;
|
std::unique_ptr<boost::asio::steady_timer> timer;
|
||||||
|
|
||||||
void Reset() {
|
void ResetTriggerState() {
|
||||||
is_triggered = false;
|
is_triggered = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
event.fflags = 0;
|
event.fflags = 0;
|
||||||
event.data = 0;
|
event.data = 0;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +86,7 @@ struct EqueueEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const EqueueEvent& ev) const {
|
bool operator==(const EqueueEvent& ev) const {
|
||||||
return ev.event.ident == event.ident;
|
return ev.event.ident == event.ident && ev.event.filter == event.filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -99,7 +102,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddEvent(EqueueEvent& event);
|
bool AddEvent(EqueueEvent& event);
|
||||||
bool RemoveEvent(u64 id);
|
bool RemoveEvent(u64 id, s16 filter);
|
||||||
int WaitForEvents(SceKernelEvent* ev, int num, u32 micros);
|
int WaitForEvents(SceKernelEvent* ev, int num, u32 micros);
|
||||||
bool TriggerEvent(u64 ident, s16 filter, void* trigger_data);
|
bool TriggerEvent(u64 ident, s16 filter, void* trigger_data);
|
||||||
int GetTriggeredEvents(SceKernelEvent* ev, int num);
|
int GetTriggeredEvents(SceKernelEvent* ev, int num);
|
||||||
|
@ -122,6 +125,8 @@ private:
|
||||||
using SceKernelUseconds = u32;
|
using SceKernelUseconds = u32;
|
||||||
using SceKernelEqueue = EqueueInternal*;
|
using SceKernelEqueue = EqueueInternal*;
|
||||||
|
|
||||||
|
u64 PS4_SYSV_ABI sceKernelGetEventData(const SceKernelEvent* ev);
|
||||||
|
|
||||||
void RegisterEventQueue(Core::Loader::SymbolsResolver* sym);
|
void RegisterEventQueue(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue