mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-31 07:43:16 +00:00
core: gpu interrupt dispatcher
This commit is contained in:
parent
581688c1ac
commit
923baf0164
9 changed files with 161 additions and 68 deletions
|
@ -7,6 +7,7 @@
|
|||
#include "core/libraries/gnmdriver/gnmdriver.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/videoout/video_out.h"
|
||||
#include "core/platform.h"
|
||||
#include "video_core/amdgpu/liverpool.h"
|
||||
#include "video_core/amdgpu/pm4_cmds.h"
|
||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||
|
@ -48,8 +49,12 @@ s32 PS4_SYSV_ABI sceGnmAddEqEvent(SceKernelEqueue eq, u64 id, void* udata) {
|
|||
kernel_event.event.udata = udata;
|
||||
eq->addEvent(kernel_event);
|
||||
|
||||
liverpool->SetEopCallback(
|
||||
[=]() { eq->triggerEvent(SceKernelEvent::Type::GfxEop, EVFILT_GRAPHICS_CORE, nullptr); });
|
||||
Platform::IrqC::Instance()->Register([=](Platform::InterruptId irq) {
|
||||
ASSERT_MSG(irq == Platform::InterruptId::GfxEop,
|
||||
"An unexpected IRQ occured"); // We need to conver IRQ# to event id and do proper
|
||||
// filtering in trigger function
|
||||
eq->triggerEvent(SceKernelEvent::Type::GfxEop, EVFILT_GRAPHICS_CORE, nullptr);
|
||||
});
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -158,6 +163,8 @@ s32 PS4_SYSV_ABI sceGnmDeleteEqEvent(SceKernelEqueue eq, u64 id) {
|
|||
}
|
||||
|
||||
eq->removeEvent(id);
|
||||
|
||||
Platform::IrqC::Instance()->Unregister();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -1356,7 +1363,7 @@ s32 PS4_SYSV_ABI sceGnmSubmitAndFlipCommandBuffers(u32 count, void* dcb_gpu_addr
|
|||
u32* dcb_sizes_in_bytes, void* ccb_gpu_addrs[],
|
||||
u32* ccb_sizes_in_bytes, u32 vo_handle,
|
||||
u32 buf_idx, u32 flip_mode, u32 flip_arg) {
|
||||
LOG_INFO(Lib_GnmDriver, "called");
|
||||
LOG_INFO(Lib_GnmDriver, "called [buf = {}]", buf_idx);
|
||||
|
||||
auto* cmdbuf = reinterpret_cast<u32*>(dcb_gpu_addrs[count - 1]);
|
||||
const auto size_dw = dcb_sizes_in_bytes[count - 1] / 4;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/time_management.h"
|
||||
#include "core/libraries/videoout/driver.h"
|
||||
#include "core/platform.h"
|
||||
|
||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||
|
||||
|
@ -199,16 +200,19 @@ void VideoOutDriver::Flip(std::chrono::microseconds timeout) {
|
|||
|
||||
// Reset flip label
|
||||
req.port->buffer_labels[req.index] = 0;
|
||||
LOG_INFO(Lib_VideoOut, "Flip done [buf = {}]", req.index);
|
||||
}
|
||||
|
||||
bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg) {
|
||||
bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
|
||||
bool is_eop /*= false*/) {
|
||||
const auto& buffer = port->buffer_slots[index];
|
||||
const auto& group = port->groups[buffer.group_index];
|
||||
auto* frame = renderer->PrepareFrame(group, buffer.address_left);
|
||||
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
if (requests.size() >= 2) {
|
||||
if (requests.size() >= port->NumRegisteredBuffers()) {
|
||||
LOG_ERROR(Lib_VideoOut, "Flip queue is full");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -218,6 +222,7 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg) {
|
|||
.index = index,
|
||||
.flip_arg = flip_arg,
|
||||
.submit_tsc = Libraries::Kernel::sceKernelReadTsc(),
|
||||
.eop = is_eop,
|
||||
});
|
||||
|
||||
port->flip_status.flipPendingNum = static_cast<int>(requests.size());
|
||||
|
|
|
@ -34,6 +34,11 @@ struct VideoOutPort {
|
|||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
[[nodiscard]] int NumRegisteredBuffers() const {
|
||||
return std::count_if(buffer_slots.cbegin(), buffer_slots.cend(),
|
||||
[](auto& buffer) { return buffer.group_index != -1; });
|
||||
}
|
||||
};
|
||||
|
||||
struct ServiceThreadParams {
|
||||
|
@ -59,7 +64,7 @@ public:
|
|||
int UnregisterBuffers(VideoOutPort* port, s32 attributeIndex);
|
||||
|
||||
void Flip(std::chrono::microseconds timeout);
|
||||
bool SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg);
|
||||
bool SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false);
|
||||
|
||||
void Vblank();
|
||||
|
||||
|
@ -70,6 +75,7 @@ private:
|
|||
s32 index;
|
||||
s64 flip_arg;
|
||||
u64 submit_tsc;
|
||||
bool eop;
|
||||
};
|
||||
|
||||
std::mutex mutex;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "core/libraries/videoout/driver.h"
|
||||
#include "core/libraries/videoout/video_out.h"
|
||||
#include "core/loader/symbols_resolver.h"
|
||||
#include "core/platform.h"
|
||||
|
||||
namespace Libraries::VideoOut {
|
||||
|
||||
|
@ -216,13 +217,17 @@ void sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr) {
|
|||
*label_addr = reinterpret_cast<uintptr_t>(port->buffer_labels.data());
|
||||
}
|
||||
|
||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void* unk) {
|
||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk) {
|
||||
auto* port = driver->GetPort(handle);
|
||||
if (!port) {
|
||||
return 0x8029000b;
|
||||
}
|
||||
|
||||
// TODO
|
||||
Platform::IrqC::Instance()->RegisterOnce([=](Platform::InterruptId irq) {
|
||||
ASSERT_MSG(irq == Platform::InterruptId::GfxEop, "An unexpected IRQ occured");
|
||||
const auto result = driver->SubmitFlip(port, buf_id, arg, true);
|
||||
ASSERT_MSG(result, "EOP flip submission failed");
|
||||
});
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ void Vblank();
|
|||
|
||||
// Internal system functions
|
||||
void sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr);
|
||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void* unk);
|
||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk);
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue