diff --git a/GLideN64/src/Config.cpp b/GLideN64/src/Config.cpp
index 6bcb520..3ccb5a8 100644
--- a/GLideN64/src/Config.cpp
+++ b/GLideN64/src/Config.cpp
@@ -132,6 +132,9 @@ void Config::resetToDefaults()
onScreenDisplay.vis = 0;
onScreenDisplay.fps = 0;
onScreenDisplay.percent = 0;
+ onScreenDisplay.internalResolution = 0;
+ onScreenDisplay.renderingResolution = 0;
+ onScreenDisplay.statistics = 0;
onScreenDisplay.pos = posBottomLeft;
for (u32 idx = 0; idx < HotKey::hkTotal; ++idx)
diff --git a/GLideN64/src/Config.h b/GLideN64/src/Config.h
index c6b62ec..4922924 100644
--- a/GLideN64/src/Config.h
+++ b/GLideN64/src/Config.h
@@ -213,6 +213,7 @@ struct Config
u32 percent;
u32 internalResolution;
u32 renderingResolution;
+ u32 statistics;
u32 pos;
} onScreenDisplay;
diff --git a/GLideN64/src/DisplayWindow.cpp b/GLideN64/src/DisplayWindow.cpp
index b5e7325..c13a587 100644
--- a/GLideN64/src/DisplayWindow.cpp
+++ b/GLideN64/src/DisplayWindow.cpp
@@ -47,6 +47,7 @@ void DisplayWindow::restart()
void DisplayWindow::swapBuffers()
{
m_drawer.drawOSD();
+ m_drawer.clearStatistics();
_swapBuffers();
if (!RSP.LLE) {
if ((config.generalEmulation.hacks & hack_doNotResetOtherModeL) == 0)
diff --git a/GLideN64/src/GLideNUI-wtl/Settings.cpp b/GLideN64/src/GLideNUI-wtl/Settings.cpp
index 40181d2..1411cbe 100644
--- a/GLideN64/src/GLideNUI-wtl/Settings.cpp
+++ b/GLideN64/src/GLideNUI-wtl/Settings.cpp
@@ -134,6 +134,7 @@ void _loadSettings(GlSettings & settings)
config.onScreenDisplay.percent = settings.value("showPercent", config.onScreenDisplay.percent).toInt();
config.onScreenDisplay.internalResolution = settings.value("showInternalResolution", config.onScreenDisplay.internalResolution).toInt();
config.onScreenDisplay.renderingResolution = settings.value("showRenderingResolution", config.onScreenDisplay.renderingResolution).toInt();
+ config.onScreenDisplay.statistics = settings.value("showStatistics", config.onScreenDisplay.statistics).toInt();
config.onScreenDisplay.pos = settings.value("osdPos", config.onScreenDisplay.pos).toInt();
settings.endGroup();
@@ -309,6 +310,7 @@ void writeSettings(const char * _strIniFolder)
settings.setValue("showInternalResolution", config.onScreenDisplay.internalResolution);
settings.setValue("showRenderingResolution", config.onScreenDisplay.renderingResolution);
settings.setValue("osdPos", config.onScreenDisplay.pos);
+ settings.setValue("showStatistics", config.onScreenDisplay.statistics);
settings.endGroup();
settings.beginGroup("debug");
diff --git a/GLideN64/src/GLideNUI/ConfigDialog.cpp b/GLideN64/src/GLideNUI/ConfigDialog.cpp
index 07b94ee..d91a09d 100644
--- a/GLideN64/src/GLideNUI/ConfigDialog.cpp
+++ b/GLideN64/src/GLideNUI/ConfigDialog.cpp
@@ -380,6 +380,7 @@ void ConfigDialog::_init(bool reInit, bool blockCustomSettings)
ui->percentCheckBox->setChecked(config.onScreenDisplay.percent != 0);
ui->internalResolutionCheckBox->setChecked(config.onScreenDisplay.internalResolution != 0);
ui->renderingResolutionCheckBox->setChecked(config.onScreenDisplay.renderingResolution != 0);
+ ui->statisticsCheckBox->setChecked(config.onScreenDisplay.statistics != 0);
// Buttons
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Save and Close"));
@@ -721,6 +722,7 @@ void ConfigDialog::accept(bool justSave) {
config.onScreenDisplay.percent = ui->percentCheckBox->isChecked() ? 1 : 0;
config.onScreenDisplay.internalResolution = ui->internalResolutionCheckBox->isChecked() ? 1 : 0;
config.onScreenDisplay.renderingResolution = ui->renderingResolutionCheckBox->isChecked() ? 1 : 0;
+ config.onScreenDisplay.statistics = ui->statisticsCheckBox->isChecked() ? 1 : 0;
for (quint32 idx = 0; idx < Config::HotKey::hkTotal; ++idx) {
config.hotkeys.keys[idx] = 0;
diff --git a/GLideN64/src/GLideNUI/Settings.cpp b/GLideN64/src/GLideNUI/Settings.cpp
index 066040b..d1c3bfe 100644
--- a/GLideN64/src/GLideNUI/Settings.cpp
+++ b/GLideN64/src/GLideNUI/Settings.cpp
@@ -133,6 +133,7 @@ void _loadSettings(QSettings & settings)
config.onScreenDisplay.percent = settings.value("showPercent", config.onScreenDisplay.percent).toInt();
config.onScreenDisplay.internalResolution = settings.value("showInternalResolution", config.onScreenDisplay.internalResolution).toInt();
config.onScreenDisplay.renderingResolution = settings.value("showRenderingResolution", config.onScreenDisplay.renderingResolution).toInt();
+ config.onScreenDisplay.statistics = settings.value("showStatistics", config.onScreenDisplay.statistics).toInt();
config.onScreenDisplay.pos = settings.value("osdPos", config.onScreenDisplay.pos).toInt();
settings.endGroup();
@@ -303,6 +304,7 @@ void writeSettings(const QString & _strIniFolder)
settings.setValue("showPercent", config.onScreenDisplay.percent);
settings.setValue("showInternalResolution", config.onScreenDisplay.internalResolution);
settings.setValue("showRenderingResolution", config.onScreenDisplay.renderingResolution);
+ settings.setValue("showStatistics", config.onScreenDisplay.statistics);
settings.setValue("osdPos", config.onScreenDisplay.pos);
settings.endGroup();
diff --git a/GLideN64/src/GLideNUI/configDialog.ui b/GLideN64/src/GLideNUI/configDialog.ui
index fb04288..c237f0e 100644
--- a/GLideN64/src/GLideNUI/configDialog.ui
+++ b/GLideN64/src/GLideNUI/configDialog.ui
@@ -2749,6 +2749,13 @@
+ -
+
+
+ Display statistics
+
+
+
-
diff --git a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp
index c9f5eb9..e31e9cb 100644
--- a/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp
+++ b/GLideN64/src/Graphics/OpenGLContext/opengl_GLInfo.cpp
@@ -181,7 +181,7 @@ void GLInfo::init() {
#ifdef OS_ANDROID
eglImage = eglImage &&
( (isGLES2 && GraphicBufferWrapper::isSupportAvailable()) || (isGLESX && GraphicBufferWrapper::isPublicSupportAvailable()) ) &&
- (renderer != Renderer::PowerVR);
+ (renderer != Renderer::PowerVR) && (renderer != Renderer::Tegra);
#endif
if (renderer == Renderer::Intel) {
diff --git a/GLideN64/src/GraphicsDrawer.cpp b/GLideN64/src/GraphicsDrawer.cpp
index a9606e8..86bf060 100644
--- a/GLideN64/src/GraphicsDrawer.cpp
+++ b/GLideN64/src/GraphicsDrawer.cpp
@@ -46,6 +46,7 @@ GraphicsDrawer::~GraphicsDrawer()
void GraphicsDrawer::addTriangle(u32 _v0, u32 _v1, u32 _v2)
{
+ m_statistics.drawnTris++;
const u32 firstIndex = triangles.num;
triangles.elements[triangles.num++] = static_cast(_v0);
triangles.elements[triangles.num++] = static_cast(_v1);
@@ -827,7 +828,7 @@ void GraphicsDrawer::drawTriangles()
if (config.frameBufferEmulation.enable != 0) {
f32 maxY;
if (config.generalEmulation.enableClipping != 0) {
- maxY = renderAndDrawTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num, m_bFlatColors);
+ maxY = renderAndDrawTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num, m_bFlatColors, m_statistics);
} else {
gfxContext.drawTriangles(triParams);
maxY = renderTriangles(triangles.vertices.data(), triangles.elements.data(), triangles.num);
@@ -896,6 +897,10 @@ void GraphicsDrawer::drawScreenSpaceTriangle(u32 _numVtx, graphics::DrawModePara
}
}
gSP.changed |= CHANGED_GEOMETRYMODE;
+ if (_mode == graphics::drawmode::TRIANGLES)
+ m_statistics.drawnTris += _numVtx / 3;
+ else if (_mode == graphics::drawmode::TRIANGLE_STRIP)
+ m_statistics.drawnTris += _numVtx - 2;
}
void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
@@ -904,7 +909,6 @@ void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
return;
_prepareDrawTriangle(DrawingState::Triangle);
-
Context::DrawTriangleParameters triParams;
triParams.mode = drawmode::TRIANGLES;
triParams.flatColors = m_bFlatColors;
@@ -913,11 +917,12 @@ void GraphicsDrawer::drawDMATriangles(u32 _numVtx)
triParams.combiner = currentCombiner();
g_debugger.addTriangles(triParams);
m_dmaVerticesNum = 0;
+ m_statistics.drawnTris += _numVtx / 3;
if (config.frameBufferEmulation.enable != 0) {
f32 maxY;
if (config.generalEmulation.enableClipping != 0) {
- maxY = renderAndDrawTriangles(m_dmaVertices.data(), nullptr, _numVtx, m_bFlatColors);
+ maxY = renderAndDrawTriangles(m_dmaVertices.data(), nullptr, _numVtx, m_bFlatColors, m_statistics);
}
else {
gfxContext.drawTriangles(triParams);
@@ -1014,6 +1019,7 @@ void GraphicsDrawer::_drawThickLine(u32 _v0, u32 _v1, float _width)
void GraphicsDrawer::drawLine(u32 _v0, u32 _v1, float _width)
{
m_texrectDrawer.draw();
+ m_statistics.lines++;
if (!_canDraw())
return;
@@ -1046,6 +1052,7 @@ void GraphicsDrawer::drawRect(int _ulx, int _uly, int _lrx, int _lry)
{
ValueKeeper otherMode(gSP.clipRatio, 1U);
m_texrectDrawer.draw();
+ m_statistics.fillRects++;
if (!_canDraw())
return;
@@ -1257,6 +1264,7 @@ void GraphicsDrawer::drawTexturedRect(const TexturedRectParams & _params)
{
gSP.changed &= ~CHANGED_GEOMETRYMODE; // Don't update cull mode
m_drawingState = DrawingState::TexRect;
+ m_statistics.texRects++;
ValueKeeper otherMode(gSP.clipRatio, 1U);
if (m_texrectDrawer.canContinue()) {
@@ -1549,6 +1557,17 @@ void GraphicsDrawer::drawText(const char *_pText, float x, float y)
g_textDrawer.drawText(_pText, x, y);
}
+void GraphicsDrawer::Statistics::clear()
+{
+ fillRects = 0;
+ texRects = 0;
+ clippedTris = 0;
+ rejectedTris = 0;
+ culledTris = 0;
+ drawnTris = 0;
+ lines = 0;
+}
+
void GraphicsDrawer::_drawOSD(const char *_pText, float _x, float & _y)
{
float tW, tH;
@@ -1580,7 +1599,8 @@ void GraphicsDrawer::drawOSD()
config.onScreenDisplay.vis |
config.onScreenDisplay.percent |
config.onScreenDisplay.internalResolution |
- config.onScreenDisplay.renderingResolution
+ config.onScreenDisplay.renderingResolution |
+ config.onScreenDisplay.statistics
) == 0 &&
m_osdMessages.empty())
return;
@@ -1612,7 +1632,7 @@ void GraphicsDrawer::drawOSD()
vShift *= 0.5f;
const float x = hp - hShift * hp;
float y = vp - vShift * vp;
- char buf[40];
+ char buf[256];
if (config.onScreenDisplay.fps) {
sprintf(buf, "%d FPS", int(perf.getFps()));
@@ -1649,6 +1669,19 @@ void GraphicsDrawer::drawOSD()
}
}
+ if (config.onScreenDisplay.statistics) {
+ if (RSP.LLE)
+ sprintf(buf, "fill rects: %3u | tex rects: %3u | triangles: %5u",
+ m_statistics.fillRects, m_statistics.texRects, m_statistics.drawnTris);
+ else
+ sprintf(buf, "fill rects: %3u | tex rects: %3u | lines: %4u | tris drawn: %4u | clipped: %4u | culled: %4u | total: %5u",
+ m_statistics.fillRects, m_statistics.texRects, m_statistics.lines,
+ m_statistics.drawnTris, m_statistics.clippedTris, m_statistics.culledTris,
+ m_statistics.drawnTris + m_statistics.clippedTris + m_statistics.culledTris);
+ _drawOSD(buf, x, y);
+ }
+
+
for (const std::string & m : m_osdMessages) {
_drawOSD(m.c_str(), x, y);
}
@@ -1685,6 +1718,15 @@ void GraphicsDrawer::clearColorBuffer(float *_pColor)
gfxContext.clearColorBuffer(0.0f, 0.0f, 0.0f, 0.0f);
}
+bool GraphicsDrawer::isClipped(u32 _v0, u32 _v1, u32 _v2) const
+{
+ if ((triangles.vertices[_v0].clip & triangles.vertices[_v1].clip & triangles.vertices[_v2].clip) != 0) {
+ m_statistics.clippedTris++;
+ return true;
+ }
+ return false;
+}
+
bool GraphicsDrawer::isRejected(u32 _v0, u32 _v1, u32 _v2) const
{
if (!GBI.isRej() || gSP.clipRatio < 2)
@@ -1707,15 +1749,23 @@ bool GraphicsDrawer::isRejected(u32 _v0, u32 _v1, u32 _v2) const
if ((v.modify & MODIFY_XY) != 0)
continue;
const f32 sx = gSP.viewport.vtrans[0] + (v.x / v.w) * gSP.viewport.vscale[0];
- if (sx < rejectBox.ulx)
+ if (sx < rejectBox.ulx) {
+ m_statistics.rejectedTris++;
return true;
- if (sx > rejectBox.lrx)
+ }
+ if (sx > rejectBox.lrx) {
+ m_statistics.rejectedTris++;
return true;
+ }
const f32 sy = gSP.viewport.vtrans[1] + (v.y / v.w) * gSP.viewport.vscale[1] * ySign;
- if (sy < rejectBox.uly)
+ if (sy < rejectBox.uly) {
+ m_statistics.rejectedTris++;
return true;
- if (sy > rejectBox.lry)
+ }
+ if (sy > rejectBox.lry) {
+ m_statistics.rejectedTris++;
return true;
+ }
}
return false;
}
diff --git a/GLideN64/src/GraphicsDrawer.h b/GLideN64/src/GraphicsDrawer.h
index bab599a..de06d59 100644
--- a/GLideN64/src/GraphicsDrawer.h
+++ b/GLideN64/src/GraphicsDrawer.h
@@ -129,10 +129,7 @@ public:
int getTrianglesCount() const { return triangles.num; }
- bool isClipped(u32 _v0, u32 _v1, u32 _v2) const
- {
- return (triangles.vertices[_v0].clip & triangles.vertices[_v1].clip & triangles.vertices[_v2].clip) != 0;
- }
+ bool isClipped(u32 _v0, u32 _v1, u32 _v2) const;
bool isRejected(u32 _v0, u32 _v1, u32 _v2) const;
@@ -161,6 +158,19 @@ public:
void setBlendMode(bool _forceLegacyBlending = false) const;
+ void clearStatistics() { m_statistics.clear(); }
+
+ struct Statistics {
+ u32 fillRects = 0;
+ u32 texRects = 0;
+ u32 clippedTris = 0;
+ u32 rejectedTris = 0;
+ u32 culledTris = 0;
+ u32 drawnTris = 0;
+ u32 lines = 0;
+ void clear();
+ };
+
private:
friend class DisplayWindow;
friend TexrectDrawer;
@@ -216,4 +226,5 @@ private:
bool m_bBGMode;
TexrectDrawer m_texrectDrawer;
OSDMessages m_osdMessages;
+ mutable Statistics m_statistics;
};
diff --git a/GLideN64/src/SoftwareRender.cpp b/GLideN64/src/SoftwareRender.cpp
index 108e485..de869e2 100644
--- a/GLideN64/src/SoftwareRender.cpp
+++ b/GLideN64/src/SoftwareRender.cpp
@@ -340,7 +340,11 @@ f32 renderTriangles(const SPVertex * _pVertices, const u16 * _pElements, u32 _nu
return maxY;
}
-f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements, bool _flatColors)
+f32 renderAndDrawTriangles(const SPVertex *_pVertices,
+ const u16 *_pElements,
+ u32 _numElements,
+ bool _flatColors,
+ GraphicsDrawer::Statistics & _statistics)
{
f32 maxY = 0.0f;
std::vector vResult;
@@ -356,17 +360,21 @@ f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u3
int dzdx = calcDzDx(pVtxClip);
vertexi vdraw[3];
for (u32 k = 0; k < 3; ++k) {
- for (u32 k = 0; k < 3; ++k) {
- const u32 idx = clockwise ? k : 3 - k - 1;
- maxY = std::max(maxY, pVtxClip[idx].y);
- vdraw[k].x = floatToFixed16(pVtxClip[idx].x);
- vdraw[k].y = floatToFixed16(pVtxClip[idx].y);
- vdraw[k].z = floatToFixed16(pVtxClip[idx].z);
- }
+ const u32 idx = clockwise ? k : 3 - k - 1;
+ maxY = std::max(maxY, pVtxClip[idx].y);
+ vdraw[k].x = floatToFixed16(pVtxClip[idx].x);
+ vdraw[k].y = floatToFixed16(pVtxClip[idx].y);
+ vdraw[k].z = floatToFixed16(pVtxClip[idx].z);
}
Rasterize(vdraw, 3, dzdx);
};
+ auto calcMaxY = [&maxY](const vertexclip* pVtxClip)
+ {
+ for (u32 k = 0; k < 3; ++k)
+ maxY = std::max(maxY, pVtxClip[k].y);
+ };
+
for (u32 i = 0; i < _numElements; i += 3) {
u32 orbits = 0;
u32 modify = 0;
@@ -381,9 +389,12 @@ f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u3
// No clipping is necessary.
vertexclip vclip[3];
bool clockwise = true;
- if (!calcScreenCoordinates(vsrc, vclip, 3, clockwise))
+ if (!calcScreenCoordinates(vsrc, vclip, 3, clockwise)) {
// Culled
+ _statistics.drawnTris--;
+ _statistics.culledTris++;
continue;
+ }
// Copy vertices to result
for (u32 k = 0; k < 3; ++k) {
@@ -395,6 +406,8 @@ f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u3
if (needResterise)
rasterise(vclip, clockwise);
+ else
+ calcMaxY(vclip);
} else {
assert(modify == 0);
// No screen space coordinates, so use clipping in homogeneous space.
@@ -408,14 +421,21 @@ f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u3
auto prevNumVtx = vResult.size();
clipInHomogeneousSpace(vCopy, vResult);
const size_t numVertex = vResult.size() - prevNumVtx;
- if (!needResterise || numVertex == 0)
+ if (!needResterise)
continue;
+ if (numVertex == 0) {
+ _statistics.drawnTris--;
+ _statistics.clippedTris++;
+ continue;
+ }
std::vector vclip(numVertex);
const bool cull = ((orbits & CLIP_W) == 0) && (gSP.viewport.vscale[0] > 0.0f);
bool clockwise = true;
if (!calcScreenCoordinates(vResult.data() + prevNumVtx, vclip.data(), numVertex, cull, clockwise)) {
vResult.resize(prevNumVtx);
+ _statistics.drawnTris--;
+ _statistics.culledTris++;
continue;
}
diff --git a/GLideN64/src/SoftwareRender.h b/GLideN64/src/SoftwareRender.h
index 518e98c..5d09317 100644
--- a/GLideN64/src/SoftwareRender.h
+++ b/GLideN64/src/SoftwareRender.h
@@ -2,22 +2,30 @@
#define SOFTWARE_RENDER_H
#include "gSP.h"
+#include "GraphicsDrawer.h"
#include "Graphics/Context.h"
/* Software render triangles to N64 depth buffer
* Coordinates of vertices must be in screen space.
* No coordinate clipping applied.
+* Return max vertex Y.
*/
f32 renderScreenSpaceTriangles(const SPVertex *_pVertices, u32 _numElements);
/* Software render triangles to N64 depth buffer
* Coordinates of vertices can be in screen space or in homogeneous space
+* Return max vertex Y.
*/
f32 renderTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements);
/* Software render triangles to N64 depth buffer and draw them with GPU
* Software clipping is used before rendering and drawing.
+* Return max vertex Y.
*/
-f32 renderAndDrawTriangles(const SPVertex *_pVertices, const u16 *_pElements, u32 _numElements, bool _flatColors);
+f32 renderAndDrawTriangles(const SPVertex *_pVertices,
+ const u16 *_pElements,
+ u32 _numElements,
+ bool _flatColors,
+ GraphicsDrawer::Statistics & _statistics);
#endif // SOFTWARE_RENDER_H
diff --git a/GLideN64/src/mupenplus/Config_mupenplus.cpp b/GLideN64/src/mupenplus/Config_mupenplus.cpp
index 40f222f..e93a509 100644
--- a/GLideN64/src/mupenplus/Config_mupenplus.cpp
+++ b/GLideN64/src/mupenplus/Config_mupenplus.cpp
@@ -285,6 +285,8 @@ bool Config_SetDefault()
assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultBool(g_configVideoGliden64, "ShowRenderingResolution", config.onScreenDisplay.renderingResolution, "Show rendering resolution.");
assert(res == M64ERR_SUCCESS);
+ res = ConfigSetDefaultBool(g_configVideoGliden64, "ShowStatistics", config.onScreenDisplay.percent, "Show statistics for drawn elements.");
+ assert(res == M64ERR_SUCCESS);
res = ConfigSetDefaultInt(g_configVideoGliden64, "CountersPos", config.onScreenDisplay.pos,
"Counters position (1=top left, 2=top center, 4=top right, 8=bottom left, 16=bottom center, 32=bottom right)");
assert(res == M64ERR_SUCCESS);
@@ -579,6 +581,7 @@ void Config_LoadConfig()
config.onScreenDisplay.percent = ConfigGetParamBool(g_configVideoGliden64, "ShowPercent");
config.onScreenDisplay.internalResolution = ConfigGetParamBool(g_configVideoGliden64, "ShowInternalResolution");
config.onScreenDisplay.renderingResolution = ConfigGetParamBool(g_configVideoGliden64, "ShowRenderingResolution");
+ config.onScreenDisplay.statistics = ConfigGetParamBool(g_configVideoGliden64, "ShowStatistics");
config.onScreenDisplay.pos = ConfigGetParamInt(g_configVideoGliden64, "CountersPos");
//#Hotkey settings