// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors. // All rights reserved. // Code licensed under the BSD License. // http://www.anki3d.org/LICENSE #include namespace anki { QueryFactory::~QueryFactory() { if(!m_chunks.isEmpty()) { ANKI_VK_LOGW("Forgot the delete some queries"); } } Error QueryFactory::newQuery(MicroQuery& handle) { ANKI_ASSERT(!handle); LockGuard lock(m_mtx); // Find a not-full chunk Chunk* chunk = nullptr; for(Chunk& c : m_chunks) { if(c.m_subAllocationCount < kMaxQueriesPerQueryChunk) { // Found one if(chunk == nullptr) { chunk = &c; } else if(c.m_subAllocationCount > chunk->m_subAllocationCount) { // To decrease fragmentation use the most full chunk chunk = &c; } } } if(chunk == nullptr) { // Create new chunk chunk = newInstance(GrMemoryPool::getSingleton()); VkQueryPoolCreateInfo ci = {}; ci.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; ci.queryType = m_poolType; ci.queryCount = kMaxQueriesPerQueryChunk; ci.pipelineStatistics = m_pplineStatisticsFlags; ANKI_VK_CHECK(vkCreateQueryPool(getVkDevice(), &ci, nullptr, &chunk->m_pool)); m_chunks.pushBack(chunk); } ANKI_ASSERT(chunk); // Allocate from chunk for(U32 i = 0; i < kMaxQueriesPerQueryChunk; ++i) { if(chunk->m_allocatedMask.get(i) == 0) { chunk->m_allocatedMask.set(i); ++chunk->m_subAllocationCount; handle.m_pool = chunk->m_pool; handle.m_queryIndex = i; handle.m_chunk = chunk; vkResetQueryPool(getVkDevice(), chunk->m_pool, handle.m_queryIndex, 1); break; } } ANKI_ASSERT(!!handle); return Error::kNone; } void QueryFactory::deleteQuery(MicroQuery& handle) { ANKI_ASSERT(handle.m_pool && handle.m_queryIndex != kMaxU32 && handle.m_chunk); LockGuard lock(m_mtx); Chunk* chunk = handle.m_chunk; ANKI_ASSERT(chunk->m_subAllocationCount > 0); --chunk->m_subAllocationCount; if(chunk->m_subAllocationCount == 0) { // Delete the chunk ANKI_ASSERT(chunk->m_allocatedMask.getAnySet()); vkDestroyQueryPool(getVkDevice(), chunk->m_pool, nullptr); m_chunks.erase(chunk); deleteInstance(GrMemoryPool::getSingleton(), chunk); } else { ANKI_ASSERT(chunk->m_allocatedMask.get(handle.m_queryIndex)); chunk->m_allocatedMask.unset(handle.m_queryIndex); } handle = {}; } } // end namespace anki