diff --git a/src/d_main.c b/src/d_main.c
index 7a8ae5f0f98b62d69e690ecaa3dbb059f2b81264..850da2f1aa3400826c3c924d55a77b9e77cf1c95 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -841,9 +841,10 @@ void D_SRB2Loop(void)
 				tictime = entertime;
 			}
 
-			dbg_entertime = entertime;
-			dbg_prevtime = prevtime;
-			dbg_tictime = tictime;
+			// I looked at the possibility of putting in a float drawer for
+			// perfstats and it's very complicated, so we'll just do this instead...
+			ps_interp_frac.value.p = (precise_t)((entertime - tictime) * 1000.0f);
+			ps_interp_lag.value.p = (precise_t)((entertime - prevtime) * 1000.0f);
 
 			if (!(paused || P_AutoPause()))
 			{
diff --git a/src/m_perfstats.c b/src/m_perfstats.c
index 9fc41000d24548deb4a58f3b5071c3f6a9fa77e1..f58959f1dc67fab0fb117cb655cfa9ce2371b2de 100644
--- a/src/m_perfstats.c
+++ b/src/m_perfstats.c
@@ -17,6 +17,7 @@
 #include "i_system.h"
 #include "z_zone.h"
 #include "p_local.h"
+#include "r_fps.h"
 
 #ifdef HWRENDER
 #include "hardware/hw_main.h"
@@ -122,6 +123,12 @@ perfstatrow_t commoncounter_rows[] = {
 	{0}
 };
 
+perfstatrow_t interpolation_rows[] = {
+	{"intpfrc", "Interp frac: ", &ps_interp_frac, PS_TIME},
+	{"intplag", "Interp lag:  ", &ps_interp_lag, PS_TIME},
+	{0}
+};
+
 #ifdef HWRENDER
 perfstatrow_t batchcount_rows[] = {
 	{"polygon", "Polygons:  ", &ps_hw_numpolys, 0},
@@ -473,6 +480,9 @@ static void PS_UpdateFrameStats(void)
 		if (PS_IsLevelActive())
 			PS_UpdateRowHistories(commoncounter_rows, true);
 
+		if (R_UsingFrameInterpolation())
+			PS_UpdateRowHistories(interpolation_rows, true);
+
 #ifdef HWRENDER
 		if (rendermode == render_opengl && cv_glbatching.value)
 		{
@@ -634,7 +644,7 @@ static void PS_DrawRenderStats(void)
 {
 	const boolean hires = PS_HighResolution();
 	const int half_row = hires ? 5 : 4;
-	int x, y;
+	int x, y, cy = 10;
 
 	PS_DrawDescriptorHeader();
 
@@ -645,7 +655,7 @@ static void PS_DrawRenderStats(void)
 	if (PS_IsLevelActive())
 	{
 		x = hires ? 115 : 90;
-		PS_DrawPerfRows(x, 10, V_BLUEMAP, commoncounter_rows);
+		cy = PS_DrawPerfRows(x, 10, V_BLUEMAP, commoncounter_rows) + half_row;
 
 #ifdef HWRENDER
 		if (rendermode == render_opengl && cv_glbatching.value)
@@ -659,6 +669,12 @@ static void PS_DrawRenderStats(void)
 		}
 #endif
 	}
+
+	if (R_UsingFrameInterpolation())
+	{
+		x = hires ? 115 : 90;
+		PS_DrawPerfRows(x, cy, V_ROSYMAP, interpolation_rows);
+	}
 }
 
 static void PS_DrawGameLogicStats(void)
diff --git a/src/r_fps.c b/src/r_fps.c
index 6307d83a1a7a780ce77e589cd7aa03d4f49429ed..b4b11a43aec63b79b4cdd40b51c224160cee12f5 100644
--- a/src/r_fps.c
+++ b/src/r_fps.c
@@ -22,6 +22,7 @@
 #include "r_state.h"
 #include "z_zone.h"
 #include "console.h" // con_startup_loadprogress
+#include "m_perfstats.h" // ps_metric_t
 #ifdef HWRENDER
 #include "hardware/hw_main.h" // for cv_glshearing
 #endif
@@ -40,7 +41,8 @@ static CV_PossibleValue_t fpscap_cons_t[] = {
 };
 consvar_t cv_fpscap = CVAR_INIT ("fpscap", "Match refresh rate", CV_SAVE, fpscap_cons_t, NULL);
 
-consvar_t cv_interpdebug = CVAR_INIT ("interpdebug", "Off", 0, CV_OnOff, NULL);
+ps_metric_t ps_interp_frac = {0};
+ps_metric_t ps_interp_lag = {0};
 
 UINT32 R_GetFramerateCap(void)
 {
diff --git a/src/r_fps.h b/src/r_fps.h
index 4a0750c3a59b2b255a625bc0a7c12b0c64261d22..cf66d72f9718de04e6d088035966e9523057fc26 100644
--- a/src/r_fps.h
+++ b/src/r_fps.h
@@ -18,9 +18,12 @@
 #include "m_fixed.h"
 #include "p_local.h"
 #include "r_state.h"
+#include "m_perfstats.h" // ps_metric_t
 
 extern consvar_t cv_fpscap;
-extern consvar_t cv_interpdebug;
+
+extern ps_metric_t ps_interp_frac;
+extern ps_metric_t ps_interp_lag;
 
 UINT32 R_GetFramerateCap(void);
 boolean R_UsingFrameInterpolation(void);
diff --git a/src/r_main.c b/src/r_main.c
index a3bddf44fa048af6aa15ed37f86b358c005434d5..896b6a29b989ab620cc263f36a871734a0d51aaf 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -1625,5 +1625,4 @@ void R_RegisterEngineStuff(void)
 
 	// Frame interpolation/uncapped
 	CV_RegisterVar(&cv_fpscap);
-	CV_RegisterVar(&cv_interpdebug);
 }
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 535c68ee89962e51bf2e6d17c58a5a33786f6d11..6ab3102524559495d78f1f1ff864497f815c9190 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -623,24 +623,6 @@ static void ST_drawDebugInfo(void)
 #undef VFLAGS
 }
 
-float dbg_entertime = 0.0f, dbg_prevtime = 0.0f, dbg_tictime = 0.0f;
-static void ST_DrawInterpDebug(void)
-{
-	// TODO: when the devmode situation stops sucking eggs,
-	// remove cv_interpdebug and use DBG_RENDER instead.
-	if (!cv_interpdebug.value || !R_UsingFrameInterpolation())
-	{
-		return;
-	}
-
-	V_DrawRightAlignedString(312, 8, V_MONOSPACE, va("enter - tic: %.3f", dbg_entertime - dbg_tictime));
-	V_DrawRightAlignedString(312, 16, V_MONOSPACE, va("enter - prev: %.3f", dbg_entertime - dbg_prevtime));
-
-	V_DrawRightAlignedString(312, 24, V_MONOSPACE, va("tic: %.3f", dbg_tictime));
-	V_DrawRightAlignedString(312, 32, V_MONOSPACE, va("prev: %.3f", dbg_prevtime));
-	V_DrawRightAlignedString(312, 40, V_MONOSPACE, va("enter: %.3f", dbg_entertime));
-}
-
 static void ST_drawScore(void)
 {
 	if (F_GetPromptHideHud(hudinfo[HUD_SCORE].y))
@@ -2775,8 +2757,6 @@ static void ST_overlayDrawer(void)
 		ST_drawInput();
 
 	ST_drawDebugInfo();
-
-	ST_DrawInterpDebug();
 }
 
 void ST_Drawer(void)
diff --git a/src/st_stuff.h b/src/st_stuff.h
index 0956bbb7d63d918fab5c2dc01d4765473b8861eb..c59bc2ac69ebe9f73fdbe6b013d7b93e739090fe 100644
--- a/src/st_stuff.h
+++ b/src/st_stuff.h
@@ -55,8 +55,6 @@ void ST_preDrawTitleCard(void);
 void ST_preLevelTitleCardDrawer(void);
 void ST_drawWipeTitleCard(void);
 
-extern float dbg_entertime, dbg_prevtime, dbg_tictime;
-
 extern tic_t lt_ticker, lt_lasttic;
 extern tic_t lt_exitticker, lt_endtime;