@@ -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=============
867883idRenderBackend::CreateRenderTargets
@@ -1165,7 +1181,7 @@ idRenderBackend::Clear
11651181void 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*/
15761626void 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