Skip to content
This repository was archived by the owner on Jun 3, 2023. It is now read-only.

Commit 7b5a142

Browse files
committed
VK: Add a timestamp query to track frame time and report via com_showFPS.
1 parent 5ba7136 commit 7b5a142

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed

neo/renderer/RenderBackend.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ struct backEndCounters_t {
5656
totalMicroSec( 0 ),
5757
shadowMicroSec( 0 ),
5858
interactionMicroSec( 0 ),
59-
shaderPassMicroSec( 0 ) {
59+
shaderPassMicroSec( 0 ),
60+
gpuMicroSec( 0 ) {
6061
}
6162

6263
int c_surfaces;
@@ -77,6 +78,7 @@ struct backEndCounters_t {
7778
uint64 depthMicroSec;
7879
uint64 interactionMicroSec;
7980
uint64 shaderPassMicroSec;
81+
uint64 gpuMicroSec;
8082
};
8183

8284
struct gfxImpParms_t {
@@ -266,6 +268,8 @@ class idRenderBackend {
266268

267269
void CreateSemaphores();
268270

271+
void CreateQueryPool();
272+
269273
void CreateSurface();
270274

271275
void CreateSwapChain();
@@ -369,6 +373,10 @@ class idRenderBackend {
369373
idArray< VkFramebuffer, NUM_FRAME_DATA > m_frameBuffers;
370374
idArray< VkSemaphore, NUM_FRAME_DATA > m_acquireSemaphores;
371375
idArray< VkSemaphore, NUM_FRAME_DATA > m_renderCompleteSemaphores;
376+
377+
idArray< uint32, NUM_FRAME_DATA > m_queryIndex;
378+
idArray< idArray< uint64, NUM_TIMESTAMP_QUERIES >, NUM_FRAME_DATA > m_queryResults;
379+
idArray< VkQueryPool, NUM_FRAME_DATA > m_queryPools;
372380
};
373381

374382
#endif

neo/renderer/RenderCommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static const int MAX_DESC_SET_WRITES = 32;
7878
static const int MAX_DESC_SET_UNIFORMS = 48;
7979
static const int MAX_IMAGE_PARMS = 16;
8080
static const int MAX_UBO_PARMS = 2;
81+
static const int NUM_TIMESTAMP_QUERIES = 16;
8182
#endif
8283

8384
// vertCacheHandle_t packs size, offset, and frame number into 64 bits

neo/renderer/RenderSystem.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,10 +1338,6 @@ idRenderSystemLocal::SwapCommandBuffers_FinishRendering
13381338
void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( frameTiming_t * frameTiming ) {
13391339
SCOPED_PROFILE_EVENT( "SwapCommandBuffers_FinishRendering" );
13401340

1341-
if ( frameTiming != NULL ) {
1342-
frameTiming->gpuTime = 0; // until shown otherwise
1343-
}
1344-
13451341
if ( !m_bInitialized ) {
13461342
return;
13471343
}
@@ -1360,6 +1356,7 @@ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( frameTiming_t * fr
13601356
frameTiming->depthTime = m_backend.m_pc.depthMicroSec;
13611357
frameTiming->interactionTime = m_backend.m_pc.interactionMicroSec;
13621358
frameTiming->shaderTime = m_backend.m_pc.shaderPassMicroSec;
1359+
frameTiming->gpuTime = m_backend.m_pc.gpuMicroSec;
13631360
}
13641361

13651362
// print any other statistics and clear all of them

neo/renderer/Vulkan/RenderBackend_VK.cpp

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,22 @@ void idRenderBackend::CreateSemaphores() {
862862
}
863863
}
864864

865+
/*
866+
===============
867+
idRenderBackend::CreateQueryPool
868+
===============
869+
*/
870+
void idRenderBackend::CreateQueryPool() {
871+
VkQueryPoolCreateInfo createInfo = {};
872+
createInfo.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
873+
createInfo.queryType = VK_QUERY_TYPE_TIMESTAMP;
874+
createInfo.queryCount = NUM_TIMESTAMP_QUERIES;
875+
876+
for ( int i = 0; i < NUM_FRAME_DATA; ++i ) {
877+
ID_VK_CHECK( vkCreateQueryPool( vkcontext.device, &createInfo, NULL, &m_queryPools[ i ] ) );
878+
}
879+
}
880+
865881
/*
866882
=============
867883
idRenderBackend::CreateRenderTargets
@@ -1165,7 +1181,7 @@ idRenderBackend::Clear
11651181
void idRenderBackend::Clear() {
11661182
m_instance = VK_NULL_HANDLE;
11671183
m_physicalDevice = VK_NULL_HANDLE;
1168-
1184+
11691185
debugReportCallback = VK_NULL_HANDLE;
11701186
m_instanceExtensions.Clear();
11711187
m_deviceExtensions.Clear();
@@ -1184,6 +1200,12 @@ void idRenderBackend::Clear() {
11841200
m_frameBuffers.Zero();
11851201
m_acquireSemaphores.Zero();
11861202
m_renderCompleteSemaphores.Zero();
1203+
1204+
m_queryIndex.Zero();
1205+
for ( int i = 0; i < NUM_FRAME_DATA; ++i ) {
1206+
m_queryResults[ i ].Zero();
1207+
}
1208+
m_queryPools.Zero();
11871209
}
11881210

11891211
/*
@@ -1228,6 +1250,9 @@ void idRenderBackend::Init() {
12281250
// Create semaphores for image acquisition and rendering completion
12291251
CreateSemaphores();
12301252

1253+
// Create Query Pool
1254+
CreateQueryPool();
1255+
12311256
// Create Command Pool
12321257
CreateCommandPool();
12331258

@@ -1317,6 +1342,11 @@ void idRenderBackend::Shutdown() {
13171342
// Destroy Command Pool
13181343
vkDestroyCommandPool( vkcontext.device, vkcontext.commandPool, NULL );
13191344

1345+
// Destroy Query Pools
1346+
for ( int i = 0; i < NUM_FRAME_DATA; ++i ) {
1347+
vkDestroyQueryPool( vkcontext.device, m_queryPools[ i ], NULL );
1348+
}
1349+
13201350
// Destroy Semaphores
13211351
for ( int i = 0; i < NUM_FRAME_DATA; ++i ) {
13221352
vkDestroySemaphore( vkcontext.device, m_acquireSemaphores[ i ], NULL );
@@ -1555,17 +1585,37 @@ void idRenderBackend::GL_StartFrame() {
15551585
stagingManager.Flush();
15561586
renderProgManager.StartFrame();
15571587

1588+
VkCommandBuffer cmdBuffer = vkcontext.commandBuffer[ vkcontext.currentFrameData ];
1589+
VkQueryPool queryPool = m_queryPools[ vkcontext.currentFrameData ];
1590+
idArray< uint64, NUM_TIMESTAMP_QUERIES > & results = m_queryResults[ vkcontext.currentFrameData ];
1591+
1592+
if ( m_queryIndex[ vkcontext.currentFrameData ] > 0 ) {
1593+
vkGetQueryPoolResults( vkcontext.device, queryPool, 0, 2,
1594+
results.ByteSize(), results.Ptr(), sizeof( uint64 ), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT );
1595+
1596+
const uint64 gpuStart = results[ 0 ];
1597+
const uint64 gpuEnd = results[ 1 ];
1598+
const uint64 tick = ( 1000 * 1000 * 1000 ) / vkcontext.gpu->props.limits.timestampPeriod;
1599+
m_pc.gpuMicroSec = ( ( gpuEnd - gpuStart ) * 1000 * 1000 ) / tick;
1600+
1601+
m_queryIndex[ vkcontext.currentFrameData ] = 0;
1602+
}
1603+
15581604
VkCommandBufferBeginInfo commandBufferBeginInfo = {};
15591605
commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1560-
ID_VK_CHECK( vkBeginCommandBuffer( vkcontext.commandBuffer[ vkcontext.currentFrameData ], &commandBufferBeginInfo ) );
1606+
ID_VK_CHECK( vkBeginCommandBuffer( cmdBuffer, &commandBufferBeginInfo ) );
1607+
1608+
vkCmdResetQueryPool( cmdBuffer, queryPool, 0, NUM_TIMESTAMP_QUERIES );
15611609

15621610
VkRenderPassBeginInfo renderPassBeginInfo = {};
15631611
renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
15641612
renderPassBeginInfo.renderPass = vkcontext.renderPass;
15651613
renderPassBeginInfo.framebuffer = m_frameBuffers[ m_currentSwapIndex ];
15661614
renderPassBeginInfo.renderArea.extent = m_swapchainExtent;
15671615

1568-
vkCmdBeginRenderPass( vkcontext.commandBuffer[ vkcontext.currentFrameData ], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE );
1616+
vkCmdBeginRenderPass( cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE );
1617+
1618+
vkCmdWriteTimestamp( cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, queryPool, m_queryIndex[ vkcontext.currentFrameData ]++ );
15691619
}
15701620

15711621
/*
@@ -1574,7 +1624,11 @@ idRenderBackend::GL_EndFrame
15741624
==================
15751625
*/
15761626
void idRenderBackend::GL_EndFrame() {
1577-
vkCmdEndRenderPass( vkcontext.commandBuffer[ vkcontext.currentFrameData ] );
1627+
VkCommandBuffer cmdBuffer = vkcontext.commandBuffer[ vkcontext.currentFrameData ];
1628+
1629+
vkCmdWriteTimestamp( cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, m_queryPools[ vkcontext.currentFrameData ], m_queryIndex[ vkcontext.currentFrameData ]++ );
1630+
1631+
vkCmdEndRenderPass( cmdBuffer );
15781632

15791633
// Transition our swap image to present.
15801634
// Do this instead of having the renderpass do the transition
@@ -1601,7 +1655,7 @@ void idRenderBackend::GL_EndFrame() {
16011655
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
16021656
0, 0, NULL, 0, NULL, 1, &barrier );
16031657

1604-
ID_VK_CHECK( vkEndCommandBuffer( vkcontext.commandBuffer[ vkcontext.currentFrameData ] ) )
1658+
ID_VK_CHECK( vkEndCommandBuffer( cmdBuffer ) )
16051659
vkcontext.commandBufferRecorded[ vkcontext.currentFrameData ] = true;
16061660

16071661
VkSemaphore * acquire = &m_acquireSemaphores[ vkcontext.currentFrameData ];
@@ -1612,7 +1666,7 @@ void idRenderBackend::GL_EndFrame() {
16121666
VkSubmitInfo submitInfo = {};
16131667
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
16141668
submitInfo.commandBufferCount = 1;
1615-
submitInfo.pCommandBuffers = &vkcontext.commandBuffer[ vkcontext.currentFrameData ];
1669+
submitInfo.pCommandBuffers = &cmdBuffer;
16161670
submitInfo.waitSemaphoreCount = 1;
16171671
submitInfo.pWaitSemaphores = acquire;
16181672
submitInfo.signalSemaphoreCount = 1;

0 commit comments

Comments
 (0)