1cb93a386Sopenharmony_ci// Copyright 2018 The SwiftShader Authors. All Rights Reserved. 2cb93a386Sopenharmony_ci// 3cb93a386Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4cb93a386Sopenharmony_ci// you may not use this file except in compliance with the License. 5cb93a386Sopenharmony_ci// You may obtain a copy of the License at 6cb93a386Sopenharmony_ci// 7cb93a386Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8cb93a386Sopenharmony_ci// 9cb93a386Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10cb93a386Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11cb93a386Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb93a386Sopenharmony_ci// See the License for the specific language governing permissions and 13cb93a386Sopenharmony_ci// limitations under the License. 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "VkQueryPool.hpp" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <chrono> 18cb93a386Sopenharmony_ci#include <cstring> 19cb93a386Sopenharmony_ci#include <new> 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_cinamespace vk { 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciQuery::Query(VkQueryType type) 24cb93a386Sopenharmony_ci : finished(marl::Event::Mode::Manual) 25cb93a386Sopenharmony_ci , state(UNAVAILABLE) 26cb93a386Sopenharmony_ci , type(type) 27cb93a386Sopenharmony_ci , value(0) 28cb93a386Sopenharmony_ci{} 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_civoid Query::reset() 31cb93a386Sopenharmony_ci{ 32cb93a386Sopenharmony_ci finished.clear(); 33cb93a386Sopenharmony_ci auto prevState = state.exchange(UNAVAILABLE); 34cb93a386Sopenharmony_ci ASSERT(prevState != ACTIVE); 35cb93a386Sopenharmony_ci value = 0; 36cb93a386Sopenharmony_ci} 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_civoid Query::start() 39cb93a386Sopenharmony_ci{ 40cb93a386Sopenharmony_ci auto prevState = state.exchange(ACTIVE); 41cb93a386Sopenharmony_ci ASSERT(prevState != FINISHED); // Must be reset first 42cb93a386Sopenharmony_ci wg.add(); 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_civoid Query::finish() 46cb93a386Sopenharmony_ci{ 47cb93a386Sopenharmony_ci if(wg.done()) 48cb93a386Sopenharmony_ci { 49cb93a386Sopenharmony_ci auto prevState = state.exchange(FINISHED); 50cb93a386Sopenharmony_ci ASSERT(prevState == ACTIVE); 51cb93a386Sopenharmony_ci finished.signal(); 52cb93a386Sopenharmony_ci } 53cb93a386Sopenharmony_ci} 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ciQuery::Data Query::getData() const 56cb93a386Sopenharmony_ci{ 57cb93a386Sopenharmony_ci Data out; 58cb93a386Sopenharmony_ci out.state = state; 59cb93a386Sopenharmony_ci out.value = value; 60cb93a386Sopenharmony_ci return out; 61cb93a386Sopenharmony_ci} 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ciVkQueryType Query::getType() const 64cb93a386Sopenharmony_ci{ 65cb93a386Sopenharmony_ci return type; 66cb93a386Sopenharmony_ci} 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_civoid Query::wait() 69cb93a386Sopenharmony_ci{ 70cb93a386Sopenharmony_ci finished.wait(); 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_civoid Query::set(int64_t v) 74cb93a386Sopenharmony_ci{ 75cb93a386Sopenharmony_ci value = v; 76cb93a386Sopenharmony_ci} 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_civoid Query::add(int64_t v) 79cb93a386Sopenharmony_ci{ 80cb93a386Sopenharmony_ci value += v; 81cb93a386Sopenharmony_ci} 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ciQueryPool::QueryPool(const VkQueryPoolCreateInfo *pCreateInfo, void *mem) 84cb93a386Sopenharmony_ci : pool(reinterpret_cast<Query *>(mem)) 85cb93a386Sopenharmony_ci , type(pCreateInfo->queryType) 86cb93a386Sopenharmony_ci , count(pCreateInfo->queryCount) 87cb93a386Sopenharmony_ci{ 88cb93a386Sopenharmony_ci // According to the Vulkan 1.2 spec, section 30. Features: 89cb93a386Sopenharmony_ci // "pipelineStatisticsQuery specifies whether the pipeline statistics 90cb93a386Sopenharmony_ci // queries are supported. If this feature is not enabled, queries of 91cb93a386Sopenharmony_ci // type VK_QUERY_TYPE_PIPELINE_STATISTICS cannot be created, and 92cb93a386Sopenharmony_ci // none of the VkQueryPipelineStatisticFlagBits bits can be set in the 93cb93a386Sopenharmony_ci // pipelineStatistics member of the VkQueryPoolCreateInfo structure." 94cb93a386Sopenharmony_ci if(type == VK_QUERY_TYPE_PIPELINE_STATISTICS) 95cb93a386Sopenharmony_ci { 96cb93a386Sopenharmony_ci UNSUPPORTED("VkPhysicalDeviceFeatures::pipelineStatisticsQuery"); 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci // Construct all queries 100cb93a386Sopenharmony_ci for(uint32_t i = 0; i < count; i++) 101cb93a386Sopenharmony_ci { 102cb93a386Sopenharmony_ci new(&pool[i]) Query(type); 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_civoid QueryPool::destroy(const VkAllocationCallbacks *pAllocator) 107cb93a386Sopenharmony_ci{ 108cb93a386Sopenharmony_ci for(uint32_t i = 0; i < count; i++) 109cb93a386Sopenharmony_ci { 110cb93a386Sopenharmony_ci pool[i].~Query(); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci vk::freeHostMemory(pool, pAllocator); 114cb93a386Sopenharmony_ci} 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_cisize_t QueryPool::ComputeRequiredAllocationSize(const VkQueryPoolCreateInfo *pCreateInfo) 117cb93a386Sopenharmony_ci{ 118cb93a386Sopenharmony_ci return sizeof(Query) * pCreateInfo->queryCount; 119cb93a386Sopenharmony_ci} 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ciVkResult QueryPool::getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize, 122cb93a386Sopenharmony_ci void *pData, VkDeviceSize stride, VkQueryResultFlags flags) const 123cb93a386Sopenharmony_ci{ 124cb93a386Sopenharmony_ci // dataSize must be large enough to contain the result of each query 125cb93a386Sopenharmony_ci ASSERT(static_cast<size_t>(stride * queryCount) <= dataSize); 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci // The sum of firstQuery and queryCount must be less than or equal to the number of queries 128cb93a386Sopenharmony_ci ASSERT((firstQuery + queryCount) <= count); 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ci VkResult result = VK_SUCCESS; 131cb93a386Sopenharmony_ci uint8_t *data = static_cast<uint8_t *>(pData); 132cb93a386Sopenharmony_ci for(uint32_t i = firstQuery; i < (firstQuery + queryCount); i++, data += stride) 133cb93a386Sopenharmony_ci { 134cb93a386Sopenharmony_ci auto &query = pool[i]; 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci if(flags & VK_QUERY_RESULT_WAIT_BIT) // Must wait for query to finish 137cb93a386Sopenharmony_ci { 138cb93a386Sopenharmony_ci query.wait(); 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci const auto current = query.getData(); 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_ci // "If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set 144cb93a386Sopenharmony_ci // then no result values are written to pData for queries that are in the 145cb93a386Sopenharmony_ci // unavailable state at the time of the call, and vkGetQueryPoolResults returns 146cb93a386Sopenharmony_ci // VK_NOT_READY. However, availability state is still written to pData for those 147cb93a386Sopenharmony_ci // queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set." 148cb93a386Sopenharmony_ci bool writeResult = true; 149cb93a386Sopenharmony_ci if(current.state == Query::ACTIVE || (current.state == Query::UNAVAILABLE && !(flags & VK_QUERY_RESULT_WAIT_BIT))) 150cb93a386Sopenharmony_ci { 151cb93a386Sopenharmony_ci result = VK_NOT_READY; 152cb93a386Sopenharmony_ci writeResult = (flags & VK_QUERY_RESULT_PARTIAL_BIT); // Allow writing partial results 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci if(flags & VK_QUERY_RESULT_64_BIT) 156cb93a386Sopenharmony_ci { 157cb93a386Sopenharmony_ci uint64_t *result64 = reinterpret_cast<uint64_t *>(data); 158cb93a386Sopenharmony_ci if(writeResult) 159cb93a386Sopenharmony_ci { 160cb93a386Sopenharmony_ci result64[0] = current.value; 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity 163cb93a386Sopenharmony_ci { 164cb93a386Sopenharmony_ci result64[1] = current.state; 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci else 168cb93a386Sopenharmony_ci { 169cb93a386Sopenharmony_ci uint32_t *result32 = reinterpret_cast<uint32_t *>(data); 170cb93a386Sopenharmony_ci if(writeResult) 171cb93a386Sopenharmony_ci { 172cb93a386Sopenharmony_ci result32[0] = static_cast<uint32_t>(current.value); 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci if(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) // Output query availablity 175cb93a386Sopenharmony_ci { 176cb93a386Sopenharmony_ci result32[1] = current.state; 177cb93a386Sopenharmony_ci } 178cb93a386Sopenharmony_ci } 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci return result; 182cb93a386Sopenharmony_ci} 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_civoid QueryPool::begin(uint32_t query, VkQueryControlFlags flags) 185cb93a386Sopenharmony_ci{ 186cb93a386Sopenharmony_ci ASSERT(query < count); 187cb93a386Sopenharmony_ci 188cb93a386Sopenharmony_ci // Only accept flags with valid bits set. 189cb93a386Sopenharmony_ci if(flags & ~(VK_QUERY_CONTROL_PRECISE_BIT)) 190cb93a386Sopenharmony_ci { 191cb93a386Sopenharmony_ci UNSUPPORTED("vkCmdBeginQuery::flags %d", int(flags)); 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci 194cb93a386Sopenharmony_ci pool[query].start(); 195cb93a386Sopenharmony_ci} 196cb93a386Sopenharmony_ci 197cb93a386Sopenharmony_civoid QueryPool::end(uint32_t query) 198cb93a386Sopenharmony_ci{ 199cb93a386Sopenharmony_ci ASSERT(query < count); 200cb93a386Sopenharmony_ci pool[query].finish(); 201cb93a386Sopenharmony_ci} 202cb93a386Sopenharmony_ci 203cb93a386Sopenharmony_civoid QueryPool::reset(uint32_t firstQuery, uint32_t queryCount) 204cb93a386Sopenharmony_ci{ 205cb93a386Sopenharmony_ci // The sum of firstQuery and queryCount must be less than or equal to the number of queries 206cb93a386Sopenharmony_ci ASSERT((firstQuery + queryCount) <= count); 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_ci for(uint32_t i = firstQuery; i < (firstQuery + queryCount); i++) 209cb93a386Sopenharmony_ci { 210cb93a386Sopenharmony_ci pool[i].reset(); 211cb93a386Sopenharmony_ci } 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_civoid QueryPool::writeTimestamp(uint32_t query) 215cb93a386Sopenharmony_ci{ 216cb93a386Sopenharmony_ci ASSERT(query < count); 217cb93a386Sopenharmony_ci ASSERT(type == VK_QUERY_TYPE_TIMESTAMP); 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci pool[query].start(); 220cb93a386Sopenharmony_ci pool[query].set(std::chrono::time_point_cast<std::chrono::nanoseconds>( 221cb93a386Sopenharmony_ci std::chrono::steady_clock::now()) 222cb93a386Sopenharmony_ci .time_since_epoch() 223cb93a386Sopenharmony_ci .count()); 224cb93a386Sopenharmony_ci pool[query].finish(); 225cb93a386Sopenharmony_ci} 226cb93a386Sopenharmony_ci 227cb93a386Sopenharmony_ci} // namespace vk 228