mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-12-17 21:42:55 +00:00
Implement displaylist event extension functions for easier game scheduling modifications (#128)
Some checks failed
validate / ubuntu (arm64, Debug) (push) Has been cancelled
validate / ubuntu (arm64, Release) (push) Has been cancelled
validate / ubuntu (x64, Debug) (push) Has been cancelled
validate / ubuntu (x64, Release) (push) Has been cancelled
validate / windows (x64, Debug) (push) Has been cancelled
validate / windows (x64, Release) (push) Has been cancelled
validate / macos (arm64, Debug) (push) Has been cancelled
validate / macos (arm64, Release) (push) Has been cancelled
validate / macos (x64, Debug) (push) Has been cancelled
validate / macos (x64, Release) (push) Has been cancelled
Some checks failed
validate / ubuntu (arm64, Debug) (push) Has been cancelled
validate / ubuntu (arm64, Release) (push) Has been cancelled
validate / ubuntu (x64, Debug) (push) Has been cancelled
validate / ubuntu (x64, Release) (push) Has been cancelled
validate / windows (x64, Debug) (push) Has been cancelled
validate / windows (x64, Release) (push) Has been cancelled
validate / macos (arm64, Debug) (push) Has been cancelled
validate / macos (arm64, Release) (push) Has been cancelled
validate / macos (x64, Debug) (push) Has been cancelled
validate / macos (x64, Release) (push) Has been cancelled
* Implement displaylist event extension functions for easier game scheduling modifications * Fix build on clang 15
This commit is contained in:
parent
dced99c0b8
commit
e8d7aec1bb
6 changed files with 129 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ add_library(librecomp STATIC
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/src/dp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/eep.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/euc-jp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/extensions.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/files.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/flash.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/heap.cpp"
|
||||
|
|
|
|||
11
librecomp/src/extensions.cpp
Normal file
11
librecomp/src/extensions.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include "recomp.h"
|
||||
#include "ultramodern/extensions.h"
|
||||
#include "librecomp/helpers.hpp"
|
||||
|
||||
extern "C" void osExQueueDisplaylistEvent_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
OSMesg mesg = _arg<1, OSMesg>(rdram, ctx);
|
||||
PTR(void) displaylist = _arg<2, PTR(void)>(rdram, ctx);
|
||||
u32 event_type = _arg<3, u32>(rdram, ctx);
|
||||
osExQueueDisplaylistEvent(mq, mesg, displaylist, event_type);
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ add_library(ultramodern STATIC
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/error_handling.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/events.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/extensions.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/input.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/mesgqueue.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/misc_ultra.cpp"
|
||||
|
|
|
|||
48
ultramodern/include/ultramodern/extensions.h
Normal file
48
ultramodern/include/ultramodern/extensions.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef __ULTRAMODERN_EXTENSIONS_H__
|
||||
#define __ULTRAMODERN_EXTENSIONS_H__
|
||||
|
||||
#if defined(mips) // Patch compilation
|
||||
#include <ultra64.h>
|
||||
#else
|
||||
#include "ultramodern/ultra64.h"
|
||||
#endif
|
||||
|
||||
#ifndef PTR
|
||||
#define PTR(x) x*
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
// Triggers when a displaylist has been submitted to the renderer.
|
||||
OS_EX_DISPLAYLIST_EVENT_SUBMITTED,
|
||||
// Triggers when a displaylist has been fully parsed by the renderer. This includes any referenced data, such
|
||||
// as vertices, matrices, and textures.
|
||||
OS_EX_DISPLAYLIST_EVENT_PARSED,
|
||||
// Triggers when rendering of a displaylist has been completed by the renderer. This only includes the
|
||||
// rendering pass that produces an image in RAM, not the high res output images that get presented to the user.
|
||||
OS_EX_DISPLAYLIST_EVENT_COMPLETED
|
||||
} DisplaylistEventType;
|
||||
|
||||
// Queues a one-time message to be sent the next time the given event type occurs for the given displaylist.
|
||||
// This allows easier detection of displaylist events without needing to patch a game's scheduler.
|
||||
// The event will be cleared after it occurs.
|
||||
// event_type must be a member of the DisplaylistEventType enum.
|
||||
void osExQueueDisplaylistEvent(PTR(OSMesgQueue) mq, OSMesg mesg, PTR(void) displaylist, u32 event_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace ultramodern {
|
||||
namespace extensions {
|
||||
void on_displaylist_submitted(PTR(u64) displaylist);
|
||||
void on_displaylist_parsed(PTR(u64) displaylist);
|
||||
void on_displaylist_completed(PTR(u64) displaylist);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "ultramodern/ultra64.h"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
#include "ultramodern/extensions.h"
|
||||
|
||||
#include "ultramodern/rsp.hpp"
|
||||
#include "ultramodern/renderer_context.hpp"
|
||||
|
|
@ -364,10 +365,17 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re
|
|||
sp_complete();
|
||||
ultramodern::measure_input_latency();
|
||||
|
||||
PTR(u64) displaylist = task_action->task.t.data_ptr;
|
||||
ultramodern::extensions::on_displaylist_submitted(displaylist);
|
||||
|
||||
[[maybe_unused]] auto renderer_start = std::chrono::high_resolution_clock::now();
|
||||
renderer_context->send_dl(&task_action->task);
|
||||
[[maybe_unused]] auto renderer_end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
dp_complete();
|
||||
// TODO hook the parsed event up to the actual parsing point when a callback is added to RT64.
|
||||
ultramodern::extensions::on_displaylist_parsed(displaylist);
|
||||
ultramodern::extensions::on_displaylist_completed(displaylist);
|
||||
// printf("Renderer ProcessDList time: %d us\n", static_cast<u32>(std::chrono::duration_cast<std::chrono::microseconds>(renderer_end - renderer_start).count()));
|
||||
}
|
||||
else if (const auto* screen_update_action = std::get_if<ScreenUpdateAction>(&action)) {
|
||||
|
|
|
|||
60
ultramodern/src/extensions.cpp
Normal file
60
ultramodern/src/extensions.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include "ultramodern/extensions.h"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
|
||||
struct DLEvent {
|
||||
PTR(OSMesgQueue) mq;
|
||||
OSMesg mesg;
|
||||
PTR(void) displaylist;
|
||||
u32 event_type;
|
||||
};
|
||||
|
||||
struct {
|
||||
struct {
|
||||
std::mutex dl_event_mutex;
|
||||
std::vector<DLEvent> pending_events;
|
||||
} dl_events;
|
||||
} extension_state;
|
||||
|
||||
extern "C" void osExQueueDisplaylistEvent(PTR(OSMesgQueue) mq, OSMesg mesg, PTR(void) displaylist, u32 event_type) {
|
||||
std::lock_guard lock{ extension_state.dl_events.dl_event_mutex };
|
||||
|
||||
assert(
|
||||
event_type == OS_EX_DISPLAYLIST_EVENT_SUBMITTED ||
|
||||
event_type == OS_EX_DISPLAYLIST_EVENT_PARSED ||
|
||||
event_type == OS_EX_DISPLAYLIST_EVENT_COMPLETED);
|
||||
|
||||
extension_state.dl_events.pending_events.emplace_back(
|
||||
DLEvent{ mq, mesg, displaylist, event_type }
|
||||
);
|
||||
}
|
||||
|
||||
void dispatch_displaylist_events(PTR(void) displaylist, u32 event_type) {
|
||||
std::lock_guard lock{ extension_state.dl_events.dl_event_mutex };
|
||||
|
||||
// Check every pending DL event to see if they match this displaylist and event type.
|
||||
for (auto iter = extension_state.dl_events.pending_events.begin(); iter != extension_state.dl_events.pending_events.end(); ) {
|
||||
if (iter->displaylist == displaylist && iter->event_type == event_type) {
|
||||
// Send the provided message to the corresponding message queue for this event, then remove this event from the queue.
|
||||
ultramodern::enqueue_external_message(iter->mq, iter->mesg, false, true);
|
||||
iter = extension_state.dl_events.pending_events.erase(iter);
|
||||
}
|
||||
else {
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ultramodern::extensions::on_displaylist_submitted(PTR(void) displaylist) {
|
||||
dispatch_displaylist_events(displaylist, OS_EX_DISPLAYLIST_EVENT_SUBMITTED);
|
||||
}
|
||||
|
||||
void ultramodern::extensions::on_displaylist_parsed(PTR(void) displaylist) {
|
||||
dispatch_displaylist_events(displaylist, OS_EX_DISPLAYLIST_EVENT_PARSED);
|
||||
}
|
||||
|
||||
void ultramodern::extensions::on_displaylist_completed(PTR(void) displaylist) {
|
||||
dispatch_displaylist_events(displaylist, OS_EX_DISPLAYLIST_EVENT_COMPLETED);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue