render: nrhi migration (D3D12+Vulkan) + authoritative character palettes

This commit is contained in:
mchughalex 2026-07-16 22:34:27 +01:00
parent 7e6d318a52
commit abe53a2fd7
5 changed files with 6745 additions and 2216 deletions

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,14 @@
#if defined(_WIN32)
#include <windows.h>
#else
#include <pthread.h>
#include <signal.h>
#include <csetjmp>
#include <mutex>
#include <rex/exception_handler.h>
#endif
namespace skate3::native_scene {
@ -54,8 +62,56 @@ __declspec(noinline) bool GuestTryCopy(void* dst, const void* src, size_t size)
}
}
#else
// POSIX guard with the same clean-failure semantics as the SEH path: a
// handler registered in the runtime's exception chain (SIGSEGV/SIGBUS both
// arrive as Code::kAccessViolation) siglongjmps back here when the fault
// happened inside the guarded copy on this thread; unrelated faults are
// declined so the runtime's own handlers (write watches, null traps) keep
// working. The previous raw std::memcpy crashed the first macOS
// native-render session (SIGBUS in _platform_memmove under
// OnRenderModeSceneExit: streaming decommitted the captured range between
// capture and decode, exactly the case the Windows guard exists for).
namespace {
thread_local volatile bool tl_in_guest_copy = false;
thread_local sigjmp_buf tl_guest_copy_jmp;
bool GuestCopyFaultHandler(rex::arch::Exception* ex, void* /*data*/) {
if (!tl_in_guest_copy ||
ex->code() != rex::arch::Exception::Code::kAccessViolation) {
return false; // not ours - keep dispatching down the chain
}
tl_in_guest_copy = false;
// Unwinds the signal frame directly; the kernel-blocked signal is
// unblocked by the sigsetjmp fault branch (savemask=0 keeps the hot path
// free of a per-call sigprocmask syscall).
siglongjmp(tl_guest_copy_jmp, 1);
}
void EnsureGuestCopyHandler() {
static std::once_flag once;
std::call_once(once, [] {
rex::arch::ExceptionHandler::Install(GuestCopyFaultHandler, nullptr);
});
}
} // namespace
bool GuestTryCopy(void* dst, const void* src, size_t size) {
EnsureGuestCopyHandler();
if (sigsetjmp(tl_guest_copy_jmp, 0) != 0) {
// Faulted mid-copy and jumped out of the signal handler: the signal is
// still in this thread's blocked mask (handler entry blocked it, the
// longjmp skipped the normal return that would restore it). Rare path -
// the syscall is fine here.
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGSEGV);
sigaddset(&set, SIGBUS);
pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
return false;
}
tl_in_guest_copy = true;
std::memcpy(dst, src, size);
tl_in_guest_copy = false;
return true;
}
#endif

View file

@ -765,9 +765,11 @@ extern "C" REX_FUNC(sub_827E5B30) {
extern "C" REX_FUNC(sub_827A52C8) {
const uint32_t parts = ctx.r3.u32;
const uint32_t count = ctx.r4.u32;
const uint32_t src_palette = ctx.r5.u32;
const uint32_t out_mat = ctx.r7.u32;
__imp__sub_827A52C8(ctx, base);
if (skate3::native_render::Enabled()) {
skate3::native_v3::OnBoneTransforms(base, parts, count);
skate3::native_v3::OnBoneTransforms(base, parts, count, src_palette, out_mat);
}
}

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit 065cade4d314f0ab34201e633ec2904857af4101
Subproject commit c807e433a783af65656ca29b9df4a45805f1a985