1/* 2 * Copyright © 2019 Red Hat. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "lvp_private.h" 25#include "pipe/p_context.h" 26 27VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateQueryPool( 28 VkDevice _device, 29 const VkQueryPoolCreateInfo* pCreateInfo, 30 const VkAllocationCallbacks* pAllocator, 31 VkQueryPool* pQueryPool) 32{ 33 LVP_FROM_HANDLE(lvp_device, device, _device); 34 35 enum pipe_query_type pipeq; 36 switch (pCreateInfo->queryType) { 37 case VK_QUERY_TYPE_OCCLUSION: 38 pipeq = PIPE_QUERY_OCCLUSION_COUNTER; 39 break; 40 case VK_QUERY_TYPE_TIMESTAMP: 41 pipeq = PIPE_QUERY_TIMESTAMP; 42 break; 43 case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT: 44 pipeq = PIPE_QUERY_SO_STATISTICS; 45 break; 46 case VK_QUERY_TYPE_PIPELINE_STATISTICS: 47 pipeq = PIPE_QUERY_PIPELINE_STATISTICS; 48 break; 49 default: 50 return VK_ERROR_FEATURE_NOT_PRESENT; 51 } 52 struct lvp_query_pool *pool; 53 uint32_t pool_size = sizeof(*pool) + pCreateInfo->queryCount * sizeof(struct pipe_query *); 54 55 pool = vk_zalloc2(&device->vk.alloc, pAllocator, 56 pool_size, 8, 57 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 58 if (!pool) 59 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 60 61 vk_object_base_init(&device->vk, &pool->base, 62 VK_OBJECT_TYPE_QUERY_POOL); 63 pool->type = pCreateInfo->queryType; 64 pool->count = pCreateInfo->queryCount; 65 pool->base_type = pipeq; 66 pool->pipeline_stats = pCreateInfo->pipelineStatistics; 67 68 *pQueryPool = lvp_query_pool_to_handle(pool); 69 return VK_SUCCESS; 70} 71 72VKAPI_ATTR void VKAPI_CALL lvp_DestroyQueryPool( 73 VkDevice _device, 74 VkQueryPool _pool, 75 const VkAllocationCallbacks* pAllocator) 76{ 77 LVP_FROM_HANDLE(lvp_device, device, _device); 78 LVP_FROM_HANDLE(lvp_query_pool, pool, _pool); 79 80 if (!pool) 81 return; 82 83 for (unsigned i = 0; i < pool->count; i++) 84 if (pool->queries[i]) 85 device->queue.ctx->destroy_query(device->queue.ctx, pool->queries[i]); 86 vk_object_base_finish(&pool->base); 87 vk_free2(&device->vk.alloc, pAllocator, pool); 88} 89 90VKAPI_ATTR VkResult VKAPI_CALL lvp_GetQueryPoolResults( 91 VkDevice _device, 92 VkQueryPool queryPool, 93 uint32_t firstQuery, 94 uint32_t queryCount, 95 size_t dataSize, 96 void* pData, 97 VkDeviceSize stride, 98 VkQueryResultFlags flags) 99{ 100 LVP_FROM_HANDLE(lvp_device, device, _device); 101 LVP_FROM_HANDLE(lvp_query_pool, pool, queryPool); 102 VkResult vk_result = VK_SUCCESS; 103 104 lvp_DeviceWaitIdle(_device); 105 106 for (unsigned i = firstQuery; i < firstQuery + queryCount; i++) { 107 uint8_t *dptr = (uint8_t *)((char *)pData + (stride * (i - firstQuery))); 108 union pipe_query_result result; 109 bool ready = false; 110 if (pool->queries[i]) { 111 ready = device->queue.ctx->get_query_result(device->queue.ctx, 112 pool->queries[i], 113 (flags & VK_QUERY_RESULT_WAIT_BIT), 114 &result); 115 } else { 116 result.u64 = 0; 117 } 118 119 if (!ready && !(flags & VK_QUERY_RESULT_PARTIAL_BIT)) 120 vk_result = VK_NOT_READY; 121 if (flags & VK_QUERY_RESULT_64_BIT) { 122 if (ready || (flags & VK_QUERY_RESULT_PARTIAL_BIT)) { 123 if (pool->type == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 124 uint32_t mask = pool->pipeline_stats; 125 uint64_t *pstats = (uint64_t *)&result.pipeline_statistics; 126 while (mask) { 127 uint32_t i = u_bit_scan(&mask); 128 129 *(uint64_t *)dptr = pstats[i]; 130 dptr += 8; 131 } 132 } else if (pool->type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) { 133 *(uint64_t *)dptr = result.so_statistics.num_primitives_written; 134 dptr += 8; 135 *(uint64_t *)dptr = result.so_statistics.primitives_storage_needed; 136 dptr += 8; 137 } else { 138 *(uint64_t *)dptr = result.u64; 139 dptr += 8; 140 } 141 } else { 142 if (pool->type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) 143 dptr += 16; 144 else 145 dptr += 8; 146 } 147 148 } else { 149 if (ready || (flags & VK_QUERY_RESULT_PARTIAL_BIT)) { 150 if (pool->type == VK_QUERY_TYPE_PIPELINE_STATISTICS) { 151 uint32_t mask = pool->pipeline_stats; 152 uint64_t *pstats = (uint64_t *)&result.pipeline_statistics; 153 while (mask) { 154 uint32_t i = u_bit_scan(&mask); 155 156 if (pstats[i] > UINT32_MAX) 157 *(uint32_t *)dptr = UINT32_MAX; 158 else 159 *(uint32_t *)dptr = pstats[i]; 160 dptr += 4; 161 } 162 } else if (pool->type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) { 163 if (result.so_statistics.num_primitives_written > UINT32_MAX) 164 *(uint32_t *)dptr = UINT32_MAX; 165 else 166 *(uint32_t *)dptr = (uint32_t)result.so_statistics.num_primitives_written; 167 dptr += 4; 168 if (result.so_statistics.primitives_storage_needed > UINT32_MAX) 169 *(uint32_t *)dptr = UINT32_MAX; 170 else 171 *(uint32_t *)dptr = (uint32_t)result.so_statistics.primitives_storage_needed; 172 dptr += 4; 173 } else { 174 if (result.u64 > UINT32_MAX) 175 *(uint32_t *)dptr = UINT32_MAX; 176 else 177 *(uint32_t *)dptr = result.u32; 178 dptr += 4; 179 } 180 } else 181 if (pool->type == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) 182 dptr += 8; 183 else 184 dptr += 4; 185 } 186 187 if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) { 188 if (flags & VK_QUERY_RESULT_64_BIT) 189 *(uint64_t *)dptr = ready; 190 else 191 *(uint32_t *)dptr = ready; 192 } 193 } 194 return vk_result; 195} 196 197VKAPI_ATTR void VKAPI_CALL lvp_ResetQueryPool( 198 VkDevice _device, 199 VkQueryPool queryPool, 200 uint32_t firstQuery, 201 uint32_t queryCount) 202{ 203 LVP_FROM_HANDLE(lvp_device, device, _device); 204 LVP_FROM_HANDLE(lvp_query_pool, pool, queryPool); 205 206 for (uint32_t i = 0; i < queryCount; i++) { 207 uint32_t idx = i + firstQuery; 208 209 if (pool->queries[idx]) { 210 device->queue.ctx->destroy_query(device->queue.ctx, pool->queries[idx]); 211 pool->queries[idx] = NULL; 212 } 213 } 214} 215