mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-10 12:54:50 -04:00
Implement unlocked framerates via interpolation (#315)
* Disable waitForTick and waitBlanking * Initial frame interpolation implementation * Initial batch of speed fixes * Fix Iron Boots * Strip dead code once used for debugging * Interpolate shadows * Revert overzealous/redundant lookups * Fix JUTFader * Fix field map cursor * Fix various particle effects * Fix Midna when riding Wolf Link * Fix title logo * Title Logo 2: Electric Boogaloo * Fixed grass and flowers * "Unlock Framerate" config option (WIP) * Wrap more things in TARGET_PC * Finish wrapping things in TARGET_PC * Missed one * Disable dComIfGd_drawXluListInvisible when interpolating --------- Co-authored-by: Luke Street <luke@street.dev>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include "JSystem/J3DGraphBase/J3DShapeMtx.h"
|
||||
#include "JSystem/J3DGraphBase/J3DSys.h"
|
||||
#include "JSystem/JKernel/JKRHeap.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
#define J3D_ASSERTMSG(LINE, COND, MSG) JUT_ASSERT_MSG(LINE, (COND) != 0, MSG)
|
||||
#define J3D_WARN1(LINE, MSG, ARG1) JUT_WARN(LINE, MSG, ARG1)
|
||||
@@ -448,6 +449,16 @@ void J3DModel::calc() {
|
||||
if (mCalcCallBack != NULL) {
|
||||
mCalcCallBack(this, 0);
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getJointNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getAnmMtx(i)), getAnmMtx(i));
|
||||
}
|
||||
|
||||
for (u16 i = 0; i < mModelData->getWEvlpMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(reinterpret_cast<const Mtx*>(getWeightAnmMtx(i)), getWeightAnmMtx(i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void J3DModel::entry() {
|
||||
@@ -484,11 +495,17 @@ void J3DModel::viewCalc() {
|
||||
if (getMtxCalcMode() == 2) {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (isCpuSkinningOn()) {
|
||||
if (getMtxCalcMode() == 2) {
|
||||
J3DCalcViewBaseMtx(j3dSys.getViewMtx(), mBaseScale, mBaseTransformMtx,
|
||||
(MtxP)&mInternalView);
|
||||
#ifdef TARGET_PC
|
||||
dusk::frame_interp::record_final_mtx_raw(&mInternalView, mInternalView);
|
||||
#endif
|
||||
}
|
||||
} else if (checkFlag(J3DMdlFlag_SkinPosCpu)) {
|
||||
mMtxBuffer->calcDrawMtx(getMtxCalcMode(), mBaseScale, mBaseTransformMtx);
|
||||
@@ -509,6 +526,12 @@ void J3DModel::viewCalc() {
|
||||
DCStoreRange(getNrmMtxPtr(), mModelData->getDrawMtxNum() * sizeof(Mtx33));
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
for (u16 i = 0; i < mModelData->getDrawMtxNum(); ++i) {
|
||||
dusk::frame_interp::record_final_mtx_raw(&getDrawMtxPtr()[i], getDrawMtxPtr()[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
prepareShapePackets();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,20 @@
|
||||
#include "JSystem/J3DGraphBase/J3DMatBlock.h"
|
||||
#include "JSystem/J3DGraphBase/J3DSys.h"
|
||||
#include "JSystem/J3DGraphBase/J3DTexture.h"
|
||||
#include "dusk/frame_interpolation.h"
|
||||
|
||||
u16 J3DShapeMtx::sMtxLoadCache[10];
|
||||
|
||||
#ifdef TARGET_PC
|
||||
static void J3DFrameInterpConcat(MtxP lhs, MtxP rhs, Mtx out) {
|
||||
if (!dusk::frame_interp::lookup_concat_replacement(lhs, rhs, out)) {
|
||||
MTXConcat(lhs, rhs, out);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define J3DFrameInterpConcat MTXConcat
|
||||
#endif
|
||||
|
||||
void J3DShapeMtx::resetMtxLoadCache() {
|
||||
sMtxLoadCache[0] =
|
||||
sMtxLoadCache[1] =
|
||||
@@ -290,7 +301,7 @@ void J3DDifferedTexMtx::loadExecute(f32 const (*param_0)[4]) {
|
||||
|
||||
void J3DShapeMtxConcatView::loadMtxConcatView_PNGP(int slot, u16 drw) const {
|
||||
Mtx m;
|
||||
MTXConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DFrameInterpConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DDifferedTexMtx::load(m);
|
||||
J3DFifoLoadPosMtxImm(m, slot * 3);
|
||||
loadNrmMtx(slot, drw, m);
|
||||
@@ -298,7 +309,7 @@ void J3DShapeMtxConcatView::loadMtxConcatView_PNGP(int slot, u16 drw) const {
|
||||
|
||||
void J3DShapeMtxConcatView::loadMtxConcatView_PCPU(int slot, u16 drw) const {
|
||||
Mtx m;
|
||||
MTXConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DFrameInterpConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DDifferedTexMtx::load(m);
|
||||
J3DFifoLoadPosMtxImm(*j3dSys.getShapePacket()->getBaseMtxPtr(), slot * 3);
|
||||
loadNrmMtx(slot, drw, m);
|
||||
@@ -306,7 +317,7 @@ void J3DShapeMtxConcatView::loadMtxConcatView_PCPU(int slot, u16 drw) const {
|
||||
|
||||
void J3DShapeMtxConcatView::loadMtxConcatView_NCPU(int slot, u16 drw) const {
|
||||
Mtx m;
|
||||
MTXConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DFrameInterpConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DDifferedTexMtx::load(m);
|
||||
J3DFifoLoadPosMtxImm(m, slot * 3);
|
||||
J3DFifoLoadNrmMtxImm(*j3dSys.getShapePacket()->getBaseMtxPtr(), slot * 3);
|
||||
@@ -318,7 +329,7 @@ void J3DShapeMtxConcatView::loadMtxConcatView_NCPU(int slot, u16 drw) const {
|
||||
void J3DShapeMtxConcatView::loadMtxConcatView_PNCPU(int slot, u16 drw) const {
|
||||
if (J3DDifferedTexMtx::sTexGenBlock != NULL) {
|
||||
Mtx m;
|
||||
MTXConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DFrameInterpConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DDifferedTexMtx::loadExecute(m);
|
||||
}
|
||||
|
||||
@@ -331,7 +342,7 @@ void J3DShapeMtxConcatView::loadMtxConcatView_PNCPU(int slot, u16 drw) const {
|
||||
|
||||
void J3DShapeMtxConcatView::loadMtxConcatView_PNGP_LOD(int slot, u16 drw) const {
|
||||
Mtx m;
|
||||
MTXConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
J3DFrameInterpConcat(*j3dSys.getShapePacket()->getBaseMtxPtr(), j3dSys.getModelDrawMtx(drw), m);
|
||||
Mtx copy;
|
||||
j3dSys.getModel()->getModelData()->getInvJointMtx(drw).to_host(copy);
|
||||
MTXConcat(m, copy, m);
|
||||
@@ -490,9 +501,11 @@ void J3DShapeMtxBBoardConcatView::load() const {
|
||||
u16 draw_mtx_index = j3dSys.getModel()->getModelData()->getDrawMtxIndex(mUseMtxIndex);
|
||||
|
||||
if (j3dSys.getModel()->getModelData()->getDrawMtxFlag(mUseMtxIndex) == 0) {
|
||||
MTXConcat(j3dSys.getViewMtx(), j3dSys.getModel()->getMtxBuffer()->getUserAnmMtx(draw_mtx_index), mtx);
|
||||
J3DFrameInterpConcat(j3dSys.getViewMtx(),
|
||||
j3dSys.getModel()->getMtxBuffer()->getUserAnmMtx(draw_mtx_index), mtx);
|
||||
} else {
|
||||
MTXConcat(j3dSys.getViewMtx(), j3dSys.getModel()->getWeightAnmMtx(draw_mtx_index), mtx);
|
||||
J3DFrameInterpConcat(j3dSys.getViewMtx(),
|
||||
j3dSys.getModel()->getWeightAnmMtx(draw_mtx_index), mtx);
|
||||
}
|
||||
|
||||
J3DCalcBBoardMtx(mtx);
|
||||
@@ -521,9 +534,11 @@ void J3DShapeMtxYBBoardConcatView::load() const {
|
||||
u16 draw_mtx_index = j3dSys.getModel()->getModelData()->getDrawMtxIndex(mUseMtxIndex);
|
||||
|
||||
if (j3dSys.getModel()->getModelData()->getDrawMtxFlag(mUseMtxIndex) == 0) {
|
||||
MTXConcat(j3dSys.getViewMtx(), j3dSys.getModel()->getMtxBuffer()->getUserAnmMtx(draw_mtx_index), mtx1);
|
||||
J3DFrameInterpConcat(j3dSys.getViewMtx(),
|
||||
j3dSys.getModel()->getMtxBuffer()->getUserAnmMtx(draw_mtx_index), mtx1);
|
||||
} else {
|
||||
MTXConcat(j3dSys.getViewMtx(), j3dSys.getModel()->getWeightAnmMtx(draw_mtx_index), mtx1);
|
||||
J3DFrameInterpConcat(j3dSys.getViewMtx(),
|
||||
j3dSys.getModel()->getWeightAnmMtx(draw_mtx_index), mtx1);
|
||||
}
|
||||
|
||||
J3DCalcYBBoardMtx(mtx1);
|
||||
|
||||
@@ -201,6 +201,14 @@ void JFWDisplay::preGX() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_PC
|
||||
static s32 s_faderSimSteps = -1;
|
||||
|
||||
void JFWDisplay::setFaderSimSteps(u32 steps) {
|
||||
s_faderSimSteps = static_cast<s32>(steps);
|
||||
}
|
||||
#endif
|
||||
|
||||
void JFWDisplay::endGX() {
|
||||
s32 bufferNum = JUTXfb::getManager()->getBufferNum();
|
||||
u16 width = JUTVideo::getManager()->getFbWidth();
|
||||
@@ -211,7 +219,26 @@ void JFWDisplay::endGX() {
|
||||
|
||||
if (mFader != NULL) {
|
||||
ortho.setPort();
|
||||
#ifdef TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
u32 advance_count = 1;
|
||||
if (s_faderSimSteps >= 0) {
|
||||
advance_count = static_cast<u32>(s_faderSimSteps);
|
||||
s_faderSimSteps = -1;
|
||||
}
|
||||
for (u32 i = 0; i < advance_count; i++) {
|
||||
mFader->control();
|
||||
}
|
||||
if (mFader->getStatus() != 1) {
|
||||
mFader->draw();
|
||||
}
|
||||
} else {
|
||||
mFader->control();
|
||||
mFader->draw();
|
||||
}
|
||||
#else
|
||||
mFader->control();
|
||||
#endif
|
||||
}
|
||||
ortho.setPort();
|
||||
JUTDbPrint::getManager()->flush();
|
||||
@@ -351,13 +378,16 @@ void JFWDisplay::waitBlanking(int param_0) {
|
||||
}
|
||||
|
||||
static void waitForTick(u32 p1, u16 p2) {
|
||||
ZoneScopedC(tracy::Color::DimGray);
|
||||
#if TARGET_PC
|
||||
#if TARGET_PC
|
||||
if (dusk::getSettings().game.enableFrameInterpolation) {
|
||||
return;
|
||||
}
|
||||
if (dusk::getTransientSettings().skipFrameRateLimit) {
|
||||
p1 = OS_TIMER_CLOCK / 120;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ZoneScopedC(tracy::Color::DimGray);
|
||||
if (p1 != 0)
|
||||
{
|
||||
static OSTime nextTick = OSGetTime();
|
||||
|
||||
@@ -19,24 +19,24 @@ JUTFader::JUTFader(int x, int y, int width, int height, JUtility::TColor pColor)
|
||||
|
||||
void JUTFader::control() {
|
||||
if (0 <= mEStatus && mEStatus-- == 0) {
|
||||
mStatus = field_0x24;
|
||||
}
|
||||
mStatus = field_0x24;
|
||||
}
|
||||
|
||||
if (mStatus == 1) {
|
||||
return;
|
||||
}
|
||||
if (mStatus == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mStatus) {
|
||||
switch (mStatus) {
|
||||
case 0:
|
||||
mColor.a = 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
#if AVOID_UB
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
mColor.a = 0xFF - ((++field_0xa * 0xFF) / field_0x8);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
@@ -45,12 +45,12 @@ void JUTFader::control() {
|
||||
|
||||
break;
|
||||
case 3:
|
||||
#if AVOID_UB
|
||||
#if AVOID_UB
|
||||
if (field_0x8 == 0) {
|
||||
mStatus = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
mColor.a = ((++field_0xa * 0xFF) / field_0x8);
|
||||
|
||||
if (field_0xa >= field_0x8) {
|
||||
@@ -58,8 +58,12 @@ void JUTFader::control() {
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
draw();
|
||||
}
|
||||
|
||||
#ifndef TARGET_PC
|
||||
// Frame interpolation: draw call moved to JFWDisplay
|
||||
draw();
|
||||
#endif
|
||||
}
|
||||
|
||||
void JUTFader::draw() {
|
||||
|
||||
Reference in New Issue
Block a user