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_DestroyQueryPool(anv_device_to_handle(device
),
55 anv_query_pool_to_handle(pool
));
58 VkResult
anv_CreateQueryPool(
60 const VkQueryPoolCreateInfo
* pCreateInfo
,
61 VkQueryPool
* pQueryPool
)
63 ANV_FROM_HANDLE(anv_device
, device
, _device
);
64 struct anv_query_pool
*pool
;
68 assert(pCreateInfo
->sType
== VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
);
70 switch (pCreateInfo
->queryType
) {
71 case VK_QUERY_TYPE_OCCLUSION
:
73 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
74 return VK_UNSUPPORTED
;
79 pool
= anv_device_alloc(device
, sizeof(*pool
), 8,
80 VK_SYSTEM_ALLOC_TYPE_API_OBJECT
);
82 return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY
);
84 pool
->base
.destructor
= anv_query_pool_destroy
;
86 pool
->type
= pCreateInfo
->queryType
;
87 size
= pCreateInfo
->slots
* sizeof(struct anv_query_pool_slot
);
88 result
= anv_bo_init_new(&pool
->bo
, device
, size
);
89 if (result
!= VK_SUCCESS
)
92 pool
->bo
.map
= anv_gem_mmap(device
, pool
->bo
.gem_handle
, 0, size
);
94 *pQueryPool
= anv_query_pool_to_handle(pool
);
99 anv_device_free(device
, pool
);
104 VkResult
anv_DestroyQueryPool(
108 ANV_FROM_HANDLE(anv_device
, device
, _device
);
109 ANV_FROM_HANDLE(anv_query_pool
, pool
, _pool
);
111 anv_gem_munmap(pool
->bo
.map
, pool
->bo
.size
);
112 anv_gem_close(device
, pool
->bo
.gem_handle
);
113 anv_device_free(device
, pool
);
118 VkResult
anv_GetQueryPoolResults(
120 VkQueryPool queryPool
,
125 VkQueryResultFlags flags
)
127 ANV_FROM_HANDLE(anv_device
, device
, _device
);
128 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
129 struct anv_query_pool_slot
*slot
= pool
->bo
.map
;
130 int64_t timeout
= INT64_MAX
;
131 uint32_t *dst32
= pData
;
132 uint64_t *dst64
= pData
;
136 if (flags
& VK_QUERY_RESULT_WITH_AVAILABILITY_BIT
) {
137 /* Where is the availabilty info supposed to go? */
138 anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
139 return VK_UNSUPPORTED
;
142 assert(pool
->type
== VK_QUERY_TYPE_OCCLUSION
);
144 if (flags
& VK_QUERY_RESULT_64_BIT
)
145 *pDataSize
= queryCount
* sizeof(uint64_t);
147 *pDataSize
= queryCount
* sizeof(uint32_t);
152 if (flags
& VK_QUERY_RESULT_WAIT_BIT
) {
153 ret
= anv_gem_wait(device
, pool
->bo
.gem_handle
, &timeout
);
155 return vk_error(VK_ERROR_UNKNOWN
);
158 for (uint32_t i
= 0; i
< queryCount
; i
++) {
159 result
= slot
[startQuery
+ i
].end
- slot
[startQuery
+ i
].begin
;
160 if (flags
& VK_QUERY_RESULT_64_BIT
) {
163 if (result
> UINT32_MAX
)
173 anv_batch_emit_ps_depth_count(struct anv_batch
*batch
,
174 struct anv_bo
*bo
, uint32_t offset
)
176 anv_batch_emit(batch
, GEN8_PIPE_CONTROL
,
177 .DestinationAddressType
= DAT_PPGTT
,
178 .PostSyncOperation
= WritePSDepthCount
,
179 .Address
= { bo
, offset
}); /* FIXME: This is only lower 32 bits */
182 void anv_CmdBeginQuery(
183 VkCmdBuffer cmdBuffer
,
184 VkQueryPool queryPool
,
186 VkQueryControlFlags flags
)
188 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
189 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
191 switch (pool
->type
) {
192 case VK_QUERY_TYPE_OCCLUSION
:
193 anv_batch_emit_ps_depth_count(&cmd_buffer
->batch
, &pool
->bo
,
194 slot
* sizeof(struct anv_query_pool_slot
));
197 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
203 void anv_CmdEndQuery(
204 VkCmdBuffer cmdBuffer
,
205 VkQueryPool queryPool
,
208 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
209 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
211 switch (pool
->type
) {
212 case VK_QUERY_TYPE_OCCLUSION
:
213 anv_batch_emit_ps_depth_count(&cmd_buffer
->batch
, &pool
->bo
,
214 slot
* sizeof(struct anv_query_pool_slot
) + 8);
217 case VK_QUERY_TYPE_PIPELINE_STATISTICS
:
223 void anv_CmdResetQueryPool(
224 VkCmdBuffer cmdBuffer
,
225 VkQueryPool queryPool
,
232 #define TIMESTAMP 0x2358
234 void anv_CmdWriteTimestamp(
235 VkCmdBuffer cmdBuffer
,
236 VkTimestampType timestampType
,
238 VkDeviceSize destOffset
)
240 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
241 ANV_FROM_HANDLE(anv_buffer
, buffer
, destBuffer
);
242 struct anv_bo
*bo
= buffer
->bo
;
244 switch (timestampType
) {
245 case VK_TIMESTAMP_TYPE_TOP
:
246 anv_batch_emit(&cmd_buffer
->batch
, GEN8_MI_STORE_REGISTER_MEM
,
247 .RegisterAddress
= TIMESTAMP
,
248 .MemoryAddress
= { bo
, buffer
->offset
+ destOffset
});
249 anv_batch_emit(&cmd_buffer
->batch
, GEN8_MI_STORE_REGISTER_MEM
,
250 .RegisterAddress
= TIMESTAMP
+ 4,
251 .MemoryAddress
= { bo
, buffer
->offset
+ destOffset
+ 4 });
254 case VK_TIMESTAMP_TYPE_BOTTOM
:
255 anv_batch_emit(&cmd_buffer
->batch
, GEN8_PIPE_CONTROL
,
256 .DestinationAddressType
= DAT_PPGTT
,
257 .PostSyncOperation
= WriteTimestamp
,
258 .Address
= /* FIXME: This is only lower 32 bits */
259 { bo
, buffer
->offset
+ destOffset
});
267 #define alu_opcode(v) __gen_field((v), 20, 31)
268 #define alu_operand1(v) __gen_field((v), 10, 19)
269 #define alu_operand2(v) __gen_field((v), 0, 9)
270 #define alu(opcode, operand1, operand2) \
271 alu_opcode(opcode) | alu_operand1(operand1) | alu_operand2(operand2)
273 #define OPCODE_NOOP 0x000
274 #define OPCODE_LOAD 0x080
275 #define OPCODE_LOADINV 0x480
276 #define OPCODE_LOAD0 0x081
277 #define OPCODE_LOAD1 0x481
278 #define OPCODE_ADD 0x100
279 #define OPCODE_SUB 0x101
280 #define OPCODE_AND 0x102
281 #define OPCODE_OR 0x103
282 #define OPCODE_XOR 0x104
283 #define OPCODE_STORE 0x180
284 #define OPCODE_STOREINV 0x580
286 #define OPERAND_R0 0x00
287 #define OPERAND_R1 0x01
288 #define OPERAND_R2 0x02
289 #define OPERAND_R3 0x03
290 #define OPERAND_R4 0x04
291 #define OPERAND_SRCA 0x20
292 #define OPERAND_SRCB 0x21
293 #define OPERAND_ACCU 0x31
294 #define OPERAND_ZF 0x32
295 #define OPERAND_CF 0x33
297 #define CS_GPR(n) (0x2600 + (n) * 8)
300 emit_load_alu_reg_u64(struct anv_batch
*batch
, uint32_t reg
,
301 struct anv_bo
*bo
, uint32_t offset
)
303 anv_batch_emit(batch
, GEN8_MI_LOAD_REGISTER_MEM
,
304 .RegisterAddress
= reg
,
305 .MemoryAddress
= { bo
, offset
});
306 anv_batch_emit(batch
, GEN8_MI_LOAD_REGISTER_MEM
,
307 .RegisterAddress
= reg
+ 4,
308 .MemoryAddress
= { bo
, offset
+ 4 });
311 void anv_CmdCopyQueryPoolResults(
312 VkCmdBuffer cmdBuffer
,
313 VkQueryPool queryPool
,
317 VkDeviceSize destOffset
,
318 VkDeviceSize destStride
,
319 VkQueryResultFlags flags
)
321 ANV_FROM_HANDLE(anv_cmd_buffer
, cmd_buffer
, cmdBuffer
);
322 ANV_FROM_HANDLE(anv_query_pool
, pool
, queryPool
);
323 ANV_FROM_HANDLE(anv_buffer
, buffer
, destBuffer
);
324 uint32_t slot_offset
, dst_offset
;
326 if (flags
& VK_QUERY_RESULT_WITH_AVAILABILITY_BIT
) {
327 /* Where is the availabilty info supposed to go? */
328 anv_finishme("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
332 assert(pool
->type
== VK_QUERY_TYPE_OCCLUSION
);
334 /* FIXME: If we're not waiting, should we just do this on the CPU? */
335 if (flags
& VK_QUERY_RESULT_WAIT_BIT
)
336 anv_batch_emit(&cmd_buffer
->batch
, GEN8_PIPE_CONTROL
,
337 .CommandStreamerStallEnable
= true,
338 .StallAtPixelScoreboard
= true);
340 dst_offset
= buffer
->offset
+ destOffset
;
341 for (uint32_t i
= 0; i
< queryCount
; i
++) {
343 slot_offset
= (startQuery
+ i
) * sizeof(struct anv_query_pool_slot
);
345 emit_load_alu_reg_u64(&cmd_buffer
->batch
, CS_GPR(0), &pool
->bo
, slot_offset
);
346 emit_load_alu_reg_u64(&cmd_buffer
->batch
, CS_GPR(1), &pool
->bo
, slot_offset
+ 8);
348 /* FIXME: We need to clamp the result for 32 bit. */
350 uint32_t *dw
= anv_batch_emitn(&cmd_buffer
->batch
, 5, GEN8_MI_MATH
);
351 dw
[1] = alu(OPCODE_LOAD
, OPERAND_SRCA
, OPERAND_R1
);
352 dw
[2] = alu(OPCODE_LOAD
, OPERAND_SRCB
, OPERAND_R0
);
353 dw
[3] = alu(OPCODE_SUB
, 0, 0);
354 dw
[4] = alu(OPCODE_STORE
, OPERAND_R2
, OPERAND_ACCU
);
356 anv_batch_emit(&cmd_buffer
->batch
, GEN8_MI_STORE_REGISTER_MEM
,
357 .RegisterAddress
= CS_GPR(2),
358 /* FIXME: This is only lower 32 bits */
359 .MemoryAddress
= { buffer
->bo
, dst_offset
});
361 if (flags
& VK_QUERY_RESULT_64_BIT
)
362 anv_batch_emit(&cmd_buffer
->batch
, GEN8_MI_STORE_REGISTER_MEM
,
363 .RegisterAddress
= CS_GPR(2) + 4,
364 /* FIXME: This is only lower 32 bits */
365 .MemoryAddress
= { buffer
->bo
, dst_offset
+ 4 });
367 dst_offset
+= destStride
;