From e07b09b4d0cad4bad1e3a0212decf10bdbdc3d73 Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Thu, 25 Feb 2021 22:00:42 +0700 Subject: [PATCH] Add Statistics OSD info. Show number of drawn rects, lines and triangles per frame. --- src/Config.cpp | 3 ++ src/Config.h | 1 + src/DisplayWindow.cpp | 1 + src/GLideNUI-wtl/Settings.cpp | 2 + src/GLideNUI/ConfigDialog.cpp | 2 + src/GLideNUI/Settings.cpp | 2 + src/GLideNUI/configDialog.ui | 7 +++ src/GraphicsDrawer.cpp | 68 ++++++++++++++++++++++++++---- src/GraphicsDrawer.h | 19 +++++++-- src/SoftwareRender.cpp | 20 +++++++-- src/SoftwareRender.h | 10 ++++- src/mupenplus/Config_mupenplus.cpp | 3 ++ 12 files changed, 121 insertions(+), 17 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 987948d5..9cf6c71e 100644 --- a/src/Config.cpp +++ b/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/src/Config.h b/src/Config.h index 1984d191..5d23e823 100644 --- a/src/Config.h +++ b/src/Config.h @@ -211,6 +211,7 @@ struct Config u32 percent; u32 internalResolution; u32 renderingResolution; + u32 statistics; u32 pos; } onScreenDisplay; diff --git a/src/DisplayWindow.cpp b/src/DisplayWindow.cpp index b5e73252..c13a5873 100644 --- a/src/DisplayWindow.cpp +++ b/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/src/GLideNUI-wtl/Settings.cpp b/src/GLideNUI-wtl/Settings.cpp index 40181d2b..1411cbeb 100644 --- a/src/GLideNUI-wtl/Settings.cpp +++ b/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/src/GLideNUI/ConfigDialog.cpp b/src/GLideNUI/ConfigDialog.cpp index 61af28d7..a99fa44d 100644 --- a/src/GLideNUI/ConfigDialog.cpp +++ b/src/GLideNUI/ConfigDialog.cpp @@ -382,6 +382,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")); @@ -722,6 +723,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/src/GLideNUI/Settings.cpp b/src/GLideNUI/Settings.cpp index a98433d7..ef828a07 100644 --- a/src/GLideNUI/Settings.cpp +++ b/src/GLideNUI/Settings.cpp @@ -135,6 +135,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(); @@ -307,6 +308,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/src/GLideNUI/configDialog.ui b/src/GLideNUI/configDialog.ui index 58e93588..5a051b0f 100644 --- a/src/GLideNUI/configDialog.ui +++ b/src/GLideNUI/configDialog.ui @@ -3369,6 +3369,13 @@ + + + + Display statistics + + + diff --git a/src/GraphicsDrawer.cpp b/src/GraphicsDrawer.cpp index a9606e8e..86bf0605 100644 --- a/src/GraphicsDrawer.cpp +++ b/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/src/GraphicsDrawer.h b/src/GraphicsDrawer.h index bab599a9..de06d595 100644 --- a/src/GraphicsDrawer.h +++ b/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/src/SoftwareRender.cpp b/src/SoftwareRender.cpp index 108e485c..87309708 100644 --- a/src/SoftwareRender.cpp +++ b/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; @@ -381,9 +385,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) { @@ -408,14 +415,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/src/SoftwareRender.h b/src/SoftwareRender.h index 518e98c8..5d093171 100644 --- a/src/SoftwareRender.h +++ b/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/src/mupenplus/Config_mupenplus.cpp b/src/mupenplus/Config_mupenplus.cpp index 40f222f8..e93a5093 100644 --- a/src/mupenplus/Config_mupenplus.cpp +++ b/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