# CapFrameX OSD with RTSS

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

1. ### TaxxorNew Member

Messages:
9
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### TaxxorNew Member

Messages:
9
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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:

SpajdrEX and Taxxor like this.
6. ### TaxxorNew Member

Messages:
9
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. ### UnwinderModeratorStaff Member

Messages:
14,921
2,050
Yep, absolutely, thanks!

8. ### TaxxorNew Member

Messages:
9
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### UnwinderModeratorStaff Member

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

11. ### TaxxorNew Member

Messages:
9
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### TaxxorNew Member

Messages:
9
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. ### ZeroStratMember

Messages:
49
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### UnwinderModeratorStaff Member

Messages:
14,921
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. ### ZeroStratMember

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

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

18. ### ZeroStratMember

Messages:
49
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. ### AstyanaxAncient Guru

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

Messages:
14,921