2 * Copyright © 2015 Intel Corporation
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:
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
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
32 struct anv_query_pool_slot
{
38 struct anv_query_pool
{
39 struct anv_object base
;
46 anv_query_pool_destroy(struct anv_device
*device
,
47 struct anv_object
*object
,
48 VkObjectType obj_type
)
50 struct anv_query_pool
*pool
= (struct anv_query_pool
*) object
;
52 assert(obj_type
== VK_OBJECT_TYPE_QUERY_POOL
);
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
);
59 VkResult
anv_CreateQueryPool(
61 const VkQueryPoolCreateInfo
* pCreateInfo
,
62 VkQueryPool
* pQueryPool
)
64 ANV_FROM_HANDLE(anv_device
, device
, _device
);
65 struct anv_query_pool
*pool
;
69 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
);
71 switch (pCreateInfo
->queryType
) {
72 case VK_QUERY_TYPE_OCCLUSION
:
74 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
75 return VK_UNSUPPORTED
;
80 pool
= anv_device_alloc(device
, sizeof(*pool
), 8,
81 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
83 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
85 pool
->base
.destructor
= anv_query_pool_destroy
;
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
)
93 pool
->bo
.map
= anv_gem_mmap(device
, pool
->bo
.gem_handle
, 0, size
);
95 *pQueryPool
= anv_query_pool_to_handle(pool
);
100 anv_device_free(device
, pool
);
105 VkResult
anv_GetQueryPoolResults(
107 VkQueryPool queryPool
,
112 VkQueryResultFlags flags
)
114 ANV_FROM_HANDLE(anv_device
, device
, _device
);
115 ANV_FROM_HANDLE(anv_query_pool
, 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
;
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
;
129 assert(pool
->type
== VK_QUERY_TYPE_OCCLUSION
);
131 if (flags
& VK_QUERY_RESULT_64_BIT
)
132 *pDataSize
= queryCount
* sizeof(uint64_t);
134 *pDataSize
= queryCount
* sizeof(uint32_t);
139 if (flags
& VK_QUERY_RESULT_WAIT_BIT
) {
140 ret
= anv_gem_wait(device
, pool
->bo
.gem_handle
, &timeout
);
142 return vk_error(VK_ERROR_UNKNOWN
);
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
) {
150 if (result
> UINT32_MAX
)
160 anv_batch_emit_ps_depth_count(struct anv_batch
*batch
,
161 struct anv_bo
*bo
, uint32_t offset
)
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 */
169 void anv_CmdBeginQuery(
170 VkCmdBuffer cmdBuffer
,
171 VkQueryPool queryPool
,
173 VkQueryControlFlags flags
)
175 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
176 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
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
));
184 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
190 void anv_CmdEndQuery(
191 VkCmdBuffer cmdBuffer
,
192 VkQueryPool queryPool
,
195 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
196 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
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);
204 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
210 void anv_CmdResetQueryPool(
211 VkCmdBuffer cmdBuffer
,
212 VkQueryPool queryPool
,
219 #define TIMESTAMP 0x2358
221 void anv_CmdWriteTimestamp(
222 VkCmdBuffer cmdBuffer
,
223 VkTimestampType timestampType
,
225 VkDeviceSize destOffset
)
227 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
228 ANV_FROM_HANDLE(anv_buffer
, buffer
, destBuffer
);
229 struct anv_bo
*bo
= buffer
->bo
;
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 });
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
});
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)
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
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
284 #define CS_GPR(n) (0x2600 + (n) * 8)
287 emit_load_alu_reg_u64(struct anv_batch
*batch
, uint32_t reg
,
288 struct anv_bo
*bo
, uint32_t offset
)
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 });
298 void anv_CmdCopyQueryPoolResults(
299 VkCmdBuffer cmdBuffer
,
300 VkQueryPool queryPool
,
304 VkDeviceSize destOffset
,
305 VkDeviceSize destStride
,
306 VkQueryResultFlags flags
)
308 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
309 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
310 ANV_FROM_HANDLE(anv_buffer
, buffer
, destBuffer
);
311 uint32_t slot_offset
, dst_offset
;
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");
319 assert(pool
->type
== VK_QUERY_TYPE_OCCLUSION
);
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);
327 dst_offset
= buffer
->offset
+ destOffset
;
328 for (uint32_t i
= 0; i
< queryCount
; i
++) {
330 slot_offset
= (startQuery
+ i
) * sizeof(struct anv_query_pool_slot
);
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);
335 /* FIXME: We need to clamp the result for 32 bit. */
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
);
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
});
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 });
354 dst_offset
+= destStride
;