Delay query until results are available.

This will query for the new values with a bit of lag, but it ignores
issues with broken drivers...
This commit is contained in:
Bartosz Taudul 2018-06-17 20:56:46 +02:00
parent 4767dbad5b
commit 53e3eee9ee

View File

@ -40,6 +40,7 @@ public:
, m_context( s_vkCtxCounter.fetch_add( 1, std::memory_order_relaxed ) ) , m_context( s_vkCtxCounter.fetch_add( 1, std::memory_order_relaxed ) )
, m_head( 0 ) , m_head( 0 )
, m_tail( 0 ) , m_tail( 0 )
, m_oldCnt( 0 )
{ {
VkPhysicalDeviceProperties prop; VkPhysicalDeviceProperties prop;
vkGetPhysicalDeviceProperties( physdev, &prop ); vkGetPhysicalDeviceProperties( physdev, &prop );
@ -107,31 +108,22 @@ public:
if( m_tail == m_head ) return; if( m_tail == m_head ) return;
auto cnt = m_head < m_tail ? QueryCount - m_tail : m_head - m_tail; unsigned int cnt;
int64_t res[QueryCount]; if( m_oldCnt != 0 )
// This memset is required, because Nvidia drivers seem to break Vulkan spec: "If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT
// is set, the final integer value written for each query is non-zero if the query's status was available or zero if the
// status was unavailable."
// Nvidia drivers in some cases do not write the non-zero value, even if the following zero values are written.
memset( res, 0xFF, sizeof( *res ) * cnt );
if( vkGetQueryPoolResults( m_device, m_query, m_tail, cnt, sizeof( res ), res, sizeof( *res ), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ) == VK_NOT_READY )
{ {
unsigned int idx; cnt = m_oldCnt;
for( idx=0; idx<cnt; idx++ ) m_oldCnt = 0;
{ }
if( res[idx] == 0 ) break; else
} {
if( idx == 0 ) return; cnt = m_head < m_tail ? QueryCount - m_tail : m_head - m_tail;
cnt = idx; }
// The spec states that the query values MUST be available: "When VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is used, int64_t res[QueryCount];
// implementations must guarantee that if they return a non-zero availability value then the numerical results must if( vkGetQueryPoolResults( m_device, m_query, m_tail, cnt, sizeof( res ), res, sizeof( *res ), VK_QUERY_RESULT_64_BIT ) == VK_NOT_READY )
// be valid". {
// In some cases Nvidia drivers can still return VK_NOT_READY here, so we have to use VK_QUERY_RESULT_WAIT_BIT. m_oldCnt = cnt;
auto status = vkGetQueryPoolResults( m_device, m_query, m_tail, cnt, sizeof( res ), res, sizeof( *res ), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT ); return;
assert( status == VK_SUCCESS );
} }
Magic magic; Magic magic;
@ -176,6 +168,7 @@ private:
unsigned int m_head; unsigned int m_head;
unsigned int m_tail; unsigned int m_tail;
unsigned int m_oldCnt;
}; };
extern VkCtxWrapper s_vkCtx; extern VkCtxWrapper s_vkCtx;