CapFrameX OSD with RTSS

Discussion in 'Rivatuner Statistics Server (RTSS) Forum' started by ZeroStrat, Nov 4, 2019.

  1. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    @Unwinder

    So for the 1% low value of a 20s Benchmark you take all the lowest FPS values until their combined frametime sum reaches 200ms and the one that is located at that 200ms point(or that theoretically would be located at 200ms if you got one leading to 190ms and the next leading to 210ms) is your 1% low value?
     
    Last edited: Aug 9, 2020
  2. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    Correct. When we discussed it @ reddit a few weeks ago I mentioned that implementation of RTSS framerate statistics calculation is open source, it can be found in RTSS SDK in RTSSFrametimePipeSample.
     
  3. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    I think it would be good if CX and AB 1% low values were comparable so maybe we should use that approach too, besides I think it's a better one anyway^^

    To clarify my example with the 20s benchmark, if you got 20 frametime values that result in 210ms and 19 that result in 190ms, would your 1% low value be the exact average of the 19th and 20th value or ìs there a more complex calculation behind it?
    Trying to keep the blog post explanation as easy as possible to the average user^^
     
  4. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    I do not average or interpolate frametimes if 1% of total benchmark time is located somewhere between 2 slowest frames in sorted frametimes array. The frame that caused cumulative/integral frametime to cross 1% time boundary is always taken as result:

    Code:
    void CFrametimeStats::AppendData(DWORD dwFrametime)
    {
        if (m_lpFpsAvgBufferData)
        {
            m_lpFpsAvgBufferData[m_dwFpsAvgBufferPos] = dwFrametime;
            m_dwFpsAvgBufferPos = (m_dwFpsAvgBufferPos + 1) & (m_dwFpsAvgBufferSize - 1);
        }
        m_fltCurFramerate = CalcFramerate();
        if (m_fltMinFramerate > m_fltCurFramerate)
            m_fltMinFramerate = m_fltCurFramerate;
        if (m_fltMaxFramerate < m_fltCurFramerate)
            m_fltMaxFramerate = m_fltCurFramerate;
        m_qwTotalTime += dwFrametime;
        m_dwFrameCount++;
        long pos = GetInsertPos(m_lpFpsLowBufferData, m_dwFpsLowBufferSize, dwFrametime);
        if ((pos != -1) && (pos < m_dwFpsLowBufferSize))
        {
            if (pos < m_dwFpsLowBufferSize - 1)
                MoveMemory(m_lpFpsLowBufferData + pos + 1, m_lpFpsLowBufferData + pos, (m_dwFpsLowBufferSize - pos - 1) * sizeof(DWORD));
            m_lpFpsLowBufferData[pos] = dwFrametime;
        }
        DWORD dw1Dot0PercentLowFrametime    = 0;
        DWORD dw0Dot1PercentLowFrametime    = 0;
        DWORDLONG qwTime                    = 0;
        DWORDLONG qw1Dot0PercentLowTime        = m_qwTotalTime / 100;
        DWORDLONG qw0Dot1PercentLowTime        = m_qwTotalTime / 1000;
        for (DWORD index=0; index<m_dwFpsLowBufferSize; index++)
        {
            DWORD dwFrametime = m_lpFpsLowBufferData[index];
            if (!dw1Dot0PercentLowFrametime)
            {
                if (qwTime + dwFrametime > qw1Dot0PercentLowTime)
                    dw1Dot0PercentLowFrametime = dwFrametime;
            }
            if (!dw0Dot1PercentLowFrametime)
            {
                if (qwTime + dwFrametime > qw0Dot1PercentLowTime)
                    dw0Dot1PercentLowFrametime = dwFrametime;
            }
            qwTime += dwFrametime;
            if (dw1Dot0PercentLowFrametime && dw0Dot1PercentLowFrametime)
                break;
        }
        if (dw1Dot0PercentLowFrametime)
            m_flt1Dot0PercentLowFramerate = 1000000.0f / dw1Dot0PercentLowFrametime;
        if (dw0Dot1PercentLowFrametime)
            m_flt0Dot1PercentLowFramerate = 1000000.0f / dw0Dot1PercentLowFrametime;
    }
    
     
    Taxxor and ZeroStrat like this.

  5. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    Seeing as it still confuses users, I think that I'll also change the way 1%/0.1% FPS lows are displayed as the graphs in OSD. So instread of seeing the graph of changing 1% low value, users will see the history of slowest frames rendered during whole benchmark session, with 1%/0.1% areas highlighted on it. Something like that: perc.png
     
    SpajdrEX and Taxxor like this.
  6. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    yeah that's looking good

    I also updated the blog post, is that explanation acceptable for you?
     
    Unwinder likes this.
  7. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    Yep, absolutely, thanks!
     
  8. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    Adding to your graph example I think the way you displayed it in the screenshot will also lead people to believe it's an average of the worst 1%/0.1% because the whole area is highlighted.

    I'd just do a single thick stroke for the relevant value. For that to be more visible, maybe cut the x-axis to show only the worst 25% instead of 100%
     
  9. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    I think I'll also add a switch for selecting percentile calculation mode to RTSS properties, so different ways of calculating x% lows will be selectable: either linear 1% calculation (1% of total frame count) or integral 1% calculation (1% of total benchmark time).
     
  10. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    Yup, possible, it is early draft/early concept yet.
     

  11. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    From my understanding, percentiles are always related to the linear number of frames so I'd differentiate the two not as selectable ways of calculating x% lows but make them two different metrics like CX does.

    That way AB can give you 1%/0.1% percentile values(if you activated them in the properties) as well as the 1%/0.1% lows the way they are now.

    Either way I believe this will require an long tooltip on that option ^^

    Naming could be difficult, 1% low percentile framerate(however "1% percentile" already implies low) and 1% low integral framerate?
     
    Last edited: Aug 9, 2020
  12. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    As far as I see it, anything that operates on sorted frametimes array, splits it on two parts and takes a frametime located on that splitting boundary is technically calculating a percentile. So it is still Nth percentile, with N calculated dynamically opposing to using fixed 99th percentile. But yes, naming is tricky with no doubts. The reviewer who asked me to add that integral 1% low metric to RTSS a few years ago calls it "time based 1% lows" vs "count based 1% lows". I call it linear vs integral/cumulative percentiles.
    I sill see no final name for those two calculation modes and it will require a long tooltip with no doubts ;)
     
  13. Taxxor

    Taxxor New Member

    Messages:
    9
    Likes Received:
    1
    GPU:
    RX5700XT Nitro+
    I thought of time based 1% percentile, making sure the naming is always making clear that it's a single percentile value instead of something else.
    You could also call it 1% linear percentile and 1% integral percentile, but "low" could mean anything as you've seen with Gamers Nexus, which were indeed the source of our x% low method^^

    We've made it more clear in CX by calling it "1% low average" instead, so your method would be a "1% low integral percentile" but since 1% percentile is already referring to low values, the low is kinda redundant here.

    We're testing your method right now and for now we're sticking with 1% percentile and 1% low and explaining the difference in the tooltip so until you come up with other names, x% low of AB and CX will give the same results
     
    Last edited: Aug 9, 2020
  14. ZeroStrat

    ZeroStrat Member

    Messages:
    49
    Likes Received:
    17
    GPU:
    RTX 2080 Ti
    @Unwinder I'm struggling to get VRAM usage infos from AMD cards. Do you have any tips for me on how to deal with the basics of this? The ADL library doesn't really seem to support such a sensor.
     
  15. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    D3DKMTQueryStatistics API is the way to go to get it on AMD and Intel iGPUs. But API is internal and it is not publicly documented.
     

  16. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    D3DKMTQueryStatistics usage example is demonstrated in MSI Afterburner SDK. GPU.DLL plugin with open source code is demonstrating implementation of dedicated/shared VRAM usage monitoring and per-node/engine GPU usage monitoring via D3DKMT.
     
    ZeroStrat likes this.
  17. ZeroStrat

    ZeroStrat Member

    Messages:
    49
    Likes Received:
    17
    GPU:
    RTX 2080 Ti
    Many thanks!

    I will never understand why AMD does not simply offer this properly in the ADL.
     
  18. ZeroStrat

    ZeroStrat Member

    Messages:
    49
    Likes Received:
    17
    GPU:
    RTX 2080 Ti
    @Unwinder Do you trace the 3D API draw calls anywhere in the software? It seems to be possible because Reshade shows it in their stats.
     
  19. Astyanax

    Astyanax Ancient Guru

    Messages:
    7,914
    Likes Received:
    2,645
    GPU:
    GTX 1080ti
    reshade is only showing its own stats.
     
  20. Unwinder

    Unwinder Moderator Staff Member

    Messages:
    14,921
    Likes Received:
    2,050
    Everything is possible but not everything is reasonable. Overlay and frametime measurement are based on 3D API call hooking and tracing. But :: Present the only call I intercept and trace now and will intercept in future builds, adding hooking for every possible 3D API draw call is good for debugging and performance profiling but it is excremely bad idea for everyday gaming and furthermore becnhmarking scenarios because it will add noticable performance overhead.
     

Share This Page