Skip to content

Commit 78ddf14

Browse files
committed
fix a performance issue in workshop gui
this fix will make the main menu render faster: - by optizing the code, reducing loops; - by skipping some runs, sacrificing update rate for performance (it's a progress bar, one visual update per second would be more than enough) the menu was running at 60-110 fps before, now it runs at 600-700 fps
1 parent f1ed077 commit 78ddf14

1 file changed

Lines changed: 96 additions & 71 deletions

File tree

src/game/client/swarm/vgui/rd_vgui_workshop_download_progress.cpp

Lines changed: 96 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -33,113 +33,138 @@ void CRD_VGUI_Workshop_Download_Progress::ApplySchemeSettings( vgui::IScheme *pS
3333

3434
void CRD_VGUI_Workshop_Download_Progress::OnThink()
3535
{
36+
static int s_nFrameSkip = 0;
37+
static int s_nLastAddonCount = -1;
38+
static int s_nInQueue = 0;
39+
static int s_iBestAddonIndex = -1;
40+
static uint64 s_nBestBytesDownloaded = 0, s_nBestBytesTotal = 0;
41+
static bool s_bFoundDownloadWithProgress = false;
42+
43+
// Only update every nth call to OnThink (reduce update rate for performance)
44+
float fTickInterval = gpGlobals->interval_per_tick;
45+
float fTickRate = (fTickInterval > 0) ? (1.0f / fTickInterval) : 0.0f;
46+
47+
if (++s_nFrameSkip < fTickRate)
48+
{
49+
return;
50+
}
51+
s_nFrameSkip = 0;
52+
3653
BaseClass::OnThink();
3754

38-
ISteamUGC *pUGC = SteamUGC();
39-
AssertOnce( pUGC );
40-
if ( !pUGC )
55+
ISteamUGC* pUGC = SteamUGC();
56+
AssertOnce(pUGC);
57+
if (!pUGC)
4158
{
4259
return;
4360
}
4461

45-
int nInQueue = 0;
46-
FOR_EACH_VEC( g_ReactiveDropWorkshop.m_EnabledAddons, i )
62+
const int addonCount = g_ReactiveDropWorkshop.m_EnabledAddons.Count();
63+
64+
// Only re-scan the addon list if the count has changed (sacrifice accuracy for speed)
65+
if (addonCount != s_nLastAddonCount)
4766
{
48-
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[i].details.m_nPublishedFileId;
49-
if ( pUGC->GetItemState( nPublishedFileID ) & k_EItemStateDownloadPending )
67+
s_nLastAddonCount = addonCount;
68+
s_nInQueue = 0;
69+
s_iBestAddonIndex = -1;
70+
s_bFoundDownloadWithProgress = false;
71+
s_nBestBytesDownloaded = 0;
72+
s_nBestBytesTotal = 0;
73+
74+
for (int i = 0; i < addonCount; ++i)
5075
{
51-
nInQueue++;
76+
const auto& addon = g_ReactiveDropWorkshop.m_EnabledAddons[i];
77+
PublishedFileId_t nPublishedFileID = addon.details.m_nPublishedFileId;
78+
uint32 itemState = pUGC->GetItemState(nPublishedFileID);
79+
80+
if (itemState & k_EItemStateDownloadPending)
81+
{
82+
++s_nInQueue;
83+
if (s_iBestAddonIndex == -1)
84+
s_iBestAddonIndex = i;
85+
}
86+
if (!s_bFoundDownloadWithProgress && (itemState & k_EItemStateDownloading))
87+
{
88+
uint64 nBytesDownloaded, nBytesTotal;
89+
if (pUGC->GetItemDownloadInfo(nPublishedFileID, &nBytesDownloaded, &nBytesTotal) && nBytesDownloaded > 0)
90+
{
91+
s_iBestAddonIndex = i;
92+
s_nBestBytesDownloaded = nBytesDownloaded;
93+
s_nBestBytesTotal = nBytesTotal;
94+
s_bFoundDownloadWithProgress = true;
95+
}
96+
}
5297
}
5398
}
5499

55-
if ( nInQueue )
100+
if (s_nInQueue)
56101
{
57102
wchar_t wszQueueCount[21];
58-
V_snwprintf( wszQueueCount, ARRAYSIZE( wszQueueCount ), L"%d", nInQueue );
103+
V_snwprintf(wszQueueCount, ARRAYSIZE(wszQueueCount), L"%d", s_nInQueue);
59104
wchar_t wszQueue[128];
60-
g_pVGuiLocalize->ConstructString( wszQueue, sizeof( wszQueue ), g_pVGuiLocalize->Find( "#workshop_number_in_queue" ), 1, wszQueueCount );
61-
m_pLblQueue->SetText( wszQueue );
62-
m_pLblQueue->SetVisible( true );
63-
SetZPos( 20 );
105+
g_pVGuiLocalize->ConstructString(wszQueue, sizeof(wszQueue), g_pVGuiLocalize->Find("#workshop_number_in_queue"), 1, wszQueueCount);
106+
m_pLblQueue->SetText(wszQueue);
107+
m_pLblQueue->SetVisible(true);
108+
SetZPos(20);
64109
}
65110
else
66111
{
67-
m_pLblQueue->SetVisible( false );
68-
SetZPos( -1 );
112+
m_pLblQueue->SetVisible(false);
113+
SetZPos(-1);
69114
}
70115

71-
int iBestAddonIndex = -1;
72-
FOR_EACH_VEC( g_ReactiveDropWorkshop.m_EnabledAddons, i )
73-
{
74-
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[i].details.m_nPublishedFileId;
75-
if ( pUGC->GetItemState( nPublishedFileID ) & k_EItemStateDownloadPending )
76-
{
77-
iBestAddonIndex = i;
78-
break;
79-
}
80-
}
81-
FOR_EACH_VEC( g_ReactiveDropWorkshop.m_EnabledAddons, i )
82-
{
83-
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[i].details.m_nPublishedFileId;
84-
if ( pUGC->GetItemState( nPublishedFileID ) & k_EItemStateDownloading )
85-
{
86-
iBestAddonIndex = i;
87-
break;
88-
}
89-
}
90-
FOR_EACH_VEC( g_ReactiveDropWorkshop.m_EnabledAddons, i )
91-
{
92-
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[i].details.m_nPublishedFileId;
93-
if ( pUGC->GetItemState( nPublishedFileID ) & k_EItemStateDownloading )
94-
{
95-
uint64 nBytesDownloaded, nBytesTotal;
96-
if ( pUGC->GetItemDownloadInfo( nPublishedFileID, &nBytesDownloaded, &nBytesTotal ) && nBytesDownloaded > 0 )
97-
{
98-
iBestAddonIndex = i;
99-
break;
100-
}
101-
}
102-
}
103-
if ( iBestAddonIndex == -1 )
116+
if (s_iBestAddonIndex == -1)
104117
{
105-
m_pPnlBackground->SetVisible( false );
106-
m_pImgPreview->SetImage( (vgui::IImage *) NULL );
107-
m_pImgPreview->SetVisible( false );
108-
m_pLblName->SetVisible( false );
109-
m_pPrgDownload->SetVisible( false );
118+
m_pPnlBackground->SetVisible(false);
119+
m_pImgPreview->SetImage((vgui::IImage*)NULL);
120+
m_pImgPreview->SetVisible(false);
121+
m_pLblName->SetVisible(false);
122+
m_pPrgDownload->SetVisible(false);
110123
return;
111124
}
112125

113-
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[iBestAddonIndex].details.m_nPublishedFileId;
114-
if ( g_ReactiveDropWorkshop.m_EnabledAddons[iBestAddonIndex].pPreviewImage )
126+
PublishedFileId_t nPublishedFileID = g_ReactiveDropWorkshop.m_EnabledAddons[s_iBestAddonIndex].details.m_nPublishedFileId;
127+
128+
if (g_ReactiveDropWorkshop.m_EnabledAddons[s_iBestAddonIndex].pPreviewImage)
115129
{
116-
// avoid a repaint if the image is the same as the one we had before.
117-
if ( m_pImgPreview->GetImage() != g_ReactiveDropWorkshop.m_EnabledAddons[iBestAddonIndex].pPreviewImage )
130+
if (m_pImgPreview->GetImage() != static_cast<vgui::IImage*>(g_ReactiveDropWorkshop.m_EnabledAddons[s_iBestAddonIndex].pPreviewImage))
118131
{
119-
m_pImgPreview->SetImage( g_ReactiveDropWorkshop.m_EnabledAddons[iBestAddonIndex].pPreviewImage );
120-
m_pImgPreview->SetVisible( true );
132+
m_pImgPreview->SetImage(static_cast<vgui::IImage*>(g_ReactiveDropWorkshop.m_EnabledAddons[s_iBestAddonIndex].pPreviewImage));
133+
m_pImgPreview->SetVisible(true);
121134
}
122135
}
123136
else
124137
{
125-
m_pImgPreview->SetImage( (vgui::IImage *) NULL );
126-
m_pImgPreview->SetVisible( false );
138+
m_pImgPreview->SetImage((vgui::IImage*)NULL);
139+
m_pImgPreview->SetVisible(false);
127140
}
128141

129-
m_pPnlBackground->SetVisible( true );
142+
m_pPnlBackground->SetVisible(true);
130143
wchar_t wszName[k_cchPublishedDocumentTitleMax];
131-
V_UTF8ToUnicode( g_ReactiveDropWorkshop.m_EnabledAddons[iBestAddonIndex].details.m_rgchTitle, wszName, sizeof( wszName ) );
132-
m_pLblName->SetText( wszName );
133-
m_pLblName->SetVisible( true );
144+
V_UTF8ToUnicode(g_ReactiveDropWorkshop.m_EnabledAddons[s_iBestAddonIndex].details.m_rgchTitle, wszName, sizeof(wszName) / sizeof(wszName[0]));
145+
m_pLblName->SetText(wszName);
146+
m_pLblName->SetVisible(true);
134147

135-
uint64 nBytesDownloaded, nBytesTotal;
136-
if ( pUGC->GetItemDownloadInfo( nPublishedFileID, &nBytesDownloaded, &nBytesTotal ) && nBytesTotal > 0 )
148+
uint64 nBytesDownloaded = s_nBestBytesDownloaded, nBytesTotal = s_nBestBytesTotal;
149+
if (!s_bFoundDownloadWithProgress)
137150
{
138-
m_pPrgDownload->SetProgress( float( nBytesDownloaded ) / float( nBytesTotal ) );
139-
m_pPrgDownload->SetVisible( true );
151+
// Only query if not already found in the loop
152+
pUGC->GetItemDownloadInfo(nPublishedFileID, &nBytesDownloaded, &nBytesTotal);
153+
154+
// We are busy, reset s_nLastAddonCount to force a re-scan
155+
s_nLastAddonCount = -1;
156+
}
157+
if (nBytesTotal > 0)
158+
{
159+
m_pPrgDownload->SetProgress(float(nBytesDownloaded) / float(nBytesTotal));
160+
m_pPrgDownload->SetVisible(true);
161+
162+
// We are done, reset s_nLastAddonCount to force a re-scan
163+
s_nLastAddonCount = -1;
140164
}
141165
else
142166
{
143-
m_pPrgDownload->SetVisible( false );
167+
// We have no work to do
168+
m_pPrgDownload->SetVisible(false);
144169
}
145170
}

0 commit comments

Comments
 (0)