vk/vulkan.h: Update clear color handling to 130
[mesa.git] / src / vulkan / query.c
1 /*
2 * Copyright © 2015 Intel Corporation
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 <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "private.h"
31
32 struct anv_query_pool_slot {
33 uint64_t begin;
34 uint64_t end;
35 uint64_t available;
36 };
37
38 struct anv_query_pool {
39 struct anv_object base;
40 VkQueryType type;
41 uint32_t slots;
42 struct anv_bo bo;
43 };
44
45 static void
46 anv_query_pool_destroy(struct anv_device *device,
47 struct anv_object *object,
48 VkObjectType obj_type)
49 {
50 struct anv_query_pool *pool = (struct anv_query_pool *) object;
51
52 assert(obj_type == VK_OBJECT_TYPE_QUERY_POOL);
53
54 anv_gem_munmap(pool->bo.map, pool->bo.size);
55 anv_gem_close(device, pool->bo.gem_handle);
56 anv_device_free(device, pool);
57 }
58
59 VkResult anv_CreateQueryPool(
60 VkDevice _device,
61 const VkQueryPoolCreateInfo* pCreateInfo,
62 VkQueryPool* pQueryPool)
63 {
64 struct anv_device *device = (struct anv_device *) _device;
65 struct anv_query_pool *pool;
66 VkResult result;
67 size_t size;
68
69 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO);
70
71 switch (pCreateInfo->queryType) {
72 case VK_QUERY_TYPE_OCCLUSION:
73 break;
74 case VK_QUERY_TYPE_PIPELINE_STATISTICS:
75 return VK_UNSUPPORTED;
76 default:
77 unreachable("");
78 }
79
80 pool = anv_device_alloc(device, sizeof(*pool), 8,
81 VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
82 if (pool == NULL)
83 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
84
85 pool->base.destructor = anv_query_pool_destroy;
86
87 pool->type = pCreateInfo->queryType;
88 size = pCreateInfo->slots * sizeof(struct anv_query_pool_slot);
89 result = anv_bo_init_new(&pool->bo, device, size);
90 if (result != VK_SUCCESS)
91 goto fail;
92
93 pool->bo.map = anv_gem_mmap(device, pool->bo.gem_handle, 0, size);
94
95 *pQueryPool = (VkQueryPool) pool;
96
97 return VK_SUCCESS;
98
99 fail:
100 anv_device_free(device, pool);
101
102 return result;
103 }
104
105 VkResult anv_GetQueryPoolResults(
106 VkDevice _device,
107 VkQueryPool queryPool,
108 uint32_t startQuery,
109 uint32_t queryCount,
110 size_t* pDataSize,
111 void* pData,
112 VkQueryResultFlags flags)
113 {
114 struct anv_device *device = (struct anv_device *) _device;
115 struct anv_query_pool *pool = (struct anv_query_pool *) queryPool;
116 struct anv_query_pool_slot *slot = pool->bo.map;
117 int64_t timeout = INT64_MAX;
118 uint32_t *dst32 = pData;
119 uint64_t *dst64 = pData;
120 uint64_t result;
121 int ret;
122
123 if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
124 /* Where is the availabilty info supposed to go? */
125 anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
126 return VK_UNSUPPORTED;
127 }
128
129 assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
130
131 if (flags & VK_QUERY_RESULT_64_BIT)
132 *pDataSize = queryCount * sizeof(uint64_t);
133 else
134 *pDataSize = queryCount * sizeof(uint32_t);
135
136 if (pData == NULL)
137 return VK_SUCCESS;
138
139 if (flags & VK_QUERY_RESULT_WAIT_BIT) {
140 ret = anv_gem_wait(device, pool->bo.gem_handle, &timeout);
141 if (ret == -1)
142 return vk_error(VK_ERROR_UNKNOWN);
143 }
144
145 for (uint32_t i = 0; i < queryCount; i++) {
146 result = slot[startQuery + i].end - slot[startQuery + i].begin;
147 if (flags & VK_QUERY_RESULT_64_BIT) {
148 *dst64++ = result;
149 } else {
150 if (result > UINT32_MAX)
151 result = UINT32_MAX;
152 *dst32++ = result;
153 }
154 }
155
156 return VK_SUCCESS;
157 }
158
159 static void
160 anv_batch_emit_ps_depth_count(struct anv_batch *batch,
161 struct anv_bo *bo, uint32_t offset)
162 {
163 anv_batch_emit(batch, GEN8_PIPE_CONTROL,
164 .DestinationAddressType = DAT_PPGTT,
165 .PostSyncOperation = WritePSDepthCount,
166 .Address = { bo, offset }); /* FIXME: This is only lower 32 bits */
167 }
168
169 void anv_CmdBeginQuery(
170 VkCmdBuffer cmdBuffer,
171 VkQueryPool queryPool,
172 uint32_t slot,
173 VkQueryControlFlags flags)
174 {
175 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *) cmdBuffer;
176 struct anv_query_pool *pool = (struct anv_query_pool *) queryPool;
177
178 switch (pool->type) {
179 case VK_QUERY_TYPE_OCCLUSION:
180 anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
181 slot * sizeof(struct anv_query_pool_slot));
182 break;
183
184 case VK_QUERY_TYPE_PIPELINE_STATISTICS:
185 default:
186 unreachable("");
187 }
188 }
189
190 void anv_CmdEndQuery(
191 VkCmdBuffer cmdBuffer,
192 VkQueryPool queryPool,
193 uint32_t slot)
194 {
195 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *) cmdBuffer;
196 struct anv_query_pool *pool = (struct anv_query_pool *) queryPool;
197
198 switch (pool->type) {
199 case VK_QUERY_TYPE_OCCLUSION:
200 anv_batch_emit_ps_depth_count(&cmd_buffer->batch, &pool->bo,
201 slot * sizeof(struct anv_query_pool_slot) + 8);
202 break;
203
204 case VK_QUERY_TYPE_PIPELINE_STATISTICS:
205 default:
206 unreachable("");
207 }
208 }
209
210 void anv_CmdResetQueryPool(
211 VkCmdBuffer cmdBuffer,
212 VkQueryPool queryPool,
213 uint32_t startQuery,
214 uint32_t queryCount)
215 {
216 stub();
217 }
218
219 #define TIMESTAMP 0x2358
220
221 void anv_CmdWriteTimestamp(
222 VkCmdBuffer cmdBuffer,
223 VkTimestampType timestampType,
224 VkBuffer destBuffer,
225 VkDeviceSize destOffset)
226 {
227 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *) cmdBuffer;
228 struct anv_buffer *buffer = (struct anv_buffer *) destBuffer;
229 struct anv_bo *bo = buffer->bo;
230
231 switch (timestampType) {
232 case VK_TIMESTAMP_TYPE_TOP:
233 anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
234 .RegisterAddress = TIMESTAMP,
235 .MemoryAddress = { bo, buffer->offset + destOffset });
236 anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
237 .RegisterAddress = TIMESTAMP + 4,
238 .MemoryAddress = { bo, buffer->offset + destOffset + 4 });
239 break;
240
241 case VK_TIMESTAMP_TYPE_BOTTOM:
242 anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
243 .DestinationAddressType = DAT_PPGTT,
244 .PostSyncOperation = WriteTimestamp,
245 .Address = /* FIXME: This is only lower 32 bits */
246 { bo, buffer->offset + destOffset });
247 break;
248
249 default:
250 break;
251 }
252 }
253
254 #define alu_opcode(v) __gen_field((v), 20, 31)
255 #define alu_operand1(v) __gen_field((v), 10, 19)
256 #define alu_operand2(v) __gen_field((v), 0, 9)
257 #define alu(opcode, operand1, operand2) \
258 alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
259
260 #define OPCODE_NOOP 0x000
261 #define OPCODE_LOAD 0x080
262 #define OPCODE_LOADINV 0x480
263 #define OPCODE_LOAD0 0x081
264 #define OPCODE_LOAD1 0x481
265 #define OPCODE_ADD 0x100
266 #define OPCODE_SUB 0x101
267 #define OPCODE_AND 0x102
268 #define OPCODE_OR 0x103
269 #define OPCODE_XOR 0x104
270 #define OPCODE_STORE 0x180
271 #define OPCODE_STOREINV 0x580
272
273 #define OPERAND_R0 0x00
274 #define OPERAND_R1 0x01
275 #define OPERAND_R2 0x02
276 #define OPERAND_R3 0x03
277 #define OPERAND_R4 0x04
278 #define OPERAND_SRCA 0x20
279 #define OPERAND_SRCB 0x21
280 #define OPERAND_ACCU 0x31
281 #define OPERAND_ZF 0x32
282 #define OPERAND_CF 0x33
283
284 #define CS_GPR(n) (0x2600 + (n) * 8)
285
286 static void
287 emit_load_alu_reg_u64(struct anv_batch *batch, uint32_t reg,
288 struct anv_bo *bo, uint32_t offset)
289 {
290 anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
291 .RegisterAddress = reg,
292 .MemoryAddress = { bo, offset });
293 anv_batch_emit(batch, GEN8_MI_LOAD_REGISTER_MEM,
294 .RegisterAddress = reg + 4,
295 .MemoryAddress = { bo, offset + 4 });
296 }
297
298 void anv_CmdCopyQueryPoolResults(
299 VkCmdBuffer cmdBuffer,
300 VkQueryPool queryPool,
301 uint32_t startQuery,
302 uint32_t queryCount,
303 VkBuffer destBuffer,
304 VkDeviceSize destOffset,
305 VkDeviceSize destStride,
306 VkQueryResultFlags flags)
307 {
308 struct anv_cmd_buffer *cmd_buffer = (struct anv_cmd_buffer *) cmdBuffer;
309 struct anv_query_pool *pool = (struct anv_query_pool *) queryPool;
310 struct anv_buffer *buffer = (struct anv_buffer *) destBuffer;
311 uint32_t slot_offset, dst_offset;
312
313 if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
314 /* Where is the availabilty info supposed to go? */
315 anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
316 return;
317 }
318
319 assert(pool->type == VK_QUERY_TYPE_OCCLUSION);
320
321 /* FIXME: If we're not waiting, should we just do this on the CPU? */
322 if (flags & VK_QUERY_RESULT_WAIT_BIT)
323 anv_batch_emit(&cmd_buffer->batch, GEN8_PIPE_CONTROL,
324 .CommandStreamerStallEnable = true,
325 .StallAtPixelScoreboard = true);
326
327 dst_offset = buffer->offset + destOffset;
328 for (uint32_t i = 0; i < queryCount; i++) {
329
330 slot_offset = (startQuery + i) * sizeof(struct anv_query_pool_slot);
331
332 emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(0), &pool->bo, slot_offset);
333 emit_load_alu_reg_u64(&cmd_buffer->batch, CS_GPR(1), &pool->bo, slot_offset + 8);
334
335 /* FIXME: We need to clamp the result for 32 bit. */
336
337 uint32_t *dw = anv_batch_emitn(&cmd_buffer->batch, 5, GEN8_MI_MATH);
338 dw[1] = alu(OPCODE_LOAD, OPERAND_SRCA, OPERAND_R1);
339 dw[2] = alu(OPCODE_LOAD, OPERAND_SRCB, OPERAND_R0);
340 dw[3] = alu(OPCODE_SUB, 0, 0);
341 dw[4] = alu(OPCODE_STORE, OPERAND_R2, OPERAND_ACCU);
342
343 anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
344 .RegisterAddress = CS_GPR(2),
345 /* FIXME: This is only lower 32 bits */
346 .MemoryAddress = { buffer->bo, dst_offset });
347
348 if (flags & VK_QUERY_RESULT_64_BIT)
349 anv_batch_emit(&cmd_buffer->batch, GEN8_MI_STORE_REGISTER_MEM,
350 .RegisterAddress = CS_GPR(2) + 4,
351 /* FIXME: This is only lower 32 bits */
352 .MemoryAddress = { buffer->bo, dst_offset + 4 });
353
354 dst_offset += destStride;
355 }
356 }