Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/virtio/vulkan/vn_query_pool.c
4560 views
1
/*
2
* Copyright 2019 Google LLC
3
* SPDX-License-Identifier: MIT
4
*
5
* based in part on anv and radv which are:
6
* Copyright © 2015 Intel Corporation
7
* Copyright © 2016 Red Hat.
8
* Copyright © 2016 Bas Nieuwenhuizen
9
*/
10
11
#include "vn_query_pool.h"
12
13
#include "venus-protocol/vn_protocol_driver_query_pool.h"
14
15
#include "vn_device.h"
16
17
/* query pool commands */
18
19
VkResult
20
vn_CreateQueryPool(VkDevice device,
21
const VkQueryPoolCreateInfo *pCreateInfo,
22
const VkAllocationCallbacks *pAllocator,
23
VkQueryPool *pQueryPool)
24
{
25
struct vn_device *dev = vn_device_from_handle(device);
26
const VkAllocationCallbacks *alloc =
27
pAllocator ? pAllocator : &dev->base.base.alloc;
28
29
struct vn_query_pool *pool =
30
vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN,
31
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
32
if (!pool)
33
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
34
35
vn_object_base_init(&pool->base, VK_OBJECT_TYPE_QUERY_POOL, &dev->base);
36
37
pool->allocator = *alloc;
38
39
switch (pCreateInfo->queryType) {
40
case VK_QUERY_TYPE_OCCLUSION:
41
pool->result_array_size = 1;
42
break;
43
case VK_QUERY_TYPE_PIPELINE_STATISTICS:
44
pool->result_array_size =
45
util_bitcount(pCreateInfo->pipelineStatistics);
46
break;
47
case VK_QUERY_TYPE_TIMESTAMP:
48
pool->result_array_size = 1;
49
break;
50
case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
51
pool->result_array_size = 2;
52
break;
53
default:
54
unreachable("bad query type");
55
break;
56
}
57
58
VkQueryPool pool_handle = vn_query_pool_to_handle(pool);
59
vn_async_vkCreateQueryPool(dev->instance, device, pCreateInfo, NULL,
60
&pool_handle);
61
62
*pQueryPool = pool_handle;
63
64
return VK_SUCCESS;
65
}
66
67
void
68
vn_DestroyQueryPool(VkDevice device,
69
VkQueryPool queryPool,
70
const VkAllocationCallbacks *pAllocator)
71
{
72
struct vn_device *dev = vn_device_from_handle(device);
73
struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool);
74
const VkAllocationCallbacks *alloc;
75
76
if (!pool)
77
return;
78
79
alloc = pAllocator ? pAllocator : &pool->allocator;
80
81
vn_async_vkDestroyQueryPool(dev->instance, device, queryPool, NULL);
82
83
vn_object_base_fini(&pool->base);
84
vk_free(alloc, pool);
85
}
86
87
void
88
vn_ResetQueryPool(VkDevice device,
89
VkQueryPool queryPool,
90
uint32_t firstQuery,
91
uint32_t queryCount)
92
{
93
struct vn_device *dev = vn_device_from_handle(device);
94
95
vn_async_vkResetQueryPool(dev->instance, device, queryPool, firstQuery,
96
queryCount);
97
}
98
99
VkResult
100
vn_GetQueryPoolResults(VkDevice device,
101
VkQueryPool queryPool,
102
uint32_t firstQuery,
103
uint32_t queryCount,
104
size_t dataSize,
105
void *pData,
106
VkDeviceSize stride,
107
VkQueryResultFlags flags)
108
{
109
struct vn_device *dev = vn_device_from_handle(device);
110
struct vn_query_pool *pool = vn_query_pool_from_handle(queryPool);
111
const VkAllocationCallbacks *alloc = &pool->allocator;
112
113
const size_t result_width = flags & VK_QUERY_RESULT_64_BIT ? 8 : 4;
114
const size_t result_size = pool->result_array_size * result_width;
115
const bool result_always_written =
116
flags & (VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_PARTIAL_BIT);
117
118
VkQueryResultFlags packed_flags = flags;
119
size_t packed_stride = result_size;
120
if (!result_always_written)
121
packed_flags |= VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
122
if (packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
123
packed_stride += result_width;
124
125
const size_t packed_size = packed_stride * queryCount;
126
void *packed_data;
127
if (result_always_written && packed_stride == stride) {
128
packed_data = pData;
129
} else {
130
packed_data = vk_alloc(alloc, packed_size, VN_DEFAULT_ALIGN,
131
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
132
if (!packed_data)
133
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
134
}
135
136
/* TODO the renderer should transparently vkCmdCopyQueryPoolResults to a
137
* coherent memory such that we can memcpy from the coherent memory to
138
* avoid this serialized round trip.
139
*/
140
VkResult result = vn_call_vkGetQueryPoolResults(
141
dev->instance, device, queryPool, firstQuery, queryCount, packed_size,
142
packed_data, packed_stride, packed_flags);
143
144
if (packed_data == pData)
145
return vn_result(dev->instance, result);
146
147
const size_t copy_size =
148
result_size +
149
(flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT ? result_width : 0);
150
const void *src = packed_data;
151
void *dst = pData;
152
if (result == VK_SUCCESS) {
153
for (uint32_t i = 0; i < queryCount; i++) {
154
memcpy(dst, src, copy_size);
155
src += packed_stride;
156
dst += stride;
157
}
158
} else if (result == VK_NOT_READY) {
159
assert(!result_always_written &&
160
(packed_flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
161
if (flags & VK_QUERY_RESULT_64_BIT) {
162
for (uint32_t i = 0; i < queryCount; i++) {
163
const bool avail = *(const uint64_t *)(src + result_size);
164
if (avail)
165
memcpy(dst, src, copy_size);
166
else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
167
*(uint64_t *)(dst + result_size) = 0;
168
169
src += packed_stride;
170
dst += stride;
171
}
172
} else {
173
for (uint32_t i = 0; i < queryCount; i++) {
174
const bool avail = *(const uint32_t *)(src + result_size);
175
if (avail)
176
memcpy(dst, src, copy_size);
177
else if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
178
*(uint32_t *)(dst + result_size) = 0;
179
180
src += packed_stride;
181
dst += stride;
182
}
183
}
184
}
185
186
vk_free(alloc, packed_data);
187
return vn_result(dev->instance, result);
188
}
189
190