| /* Returns the IOVA of a given uint64_t field in a given slot of a query | /* Returns the IOVA of a given uint64_t field in a given slot of a query | ||||
| * pool. | * pool. | ||||
| */ | */ | ||||
| static uint64_t query_address(struct tu_query_pool *pool, uint32_t query, | |||||
| static uint64_t query_iova(struct tu_query_pool *pool, uint32_t query, | |||||
| uint32_t index) { | uint32_t index) { | ||||
| return (pool->bo->iova) + (pool->stride * query) + | |||||
| (index * sizeof(uint64_t)); | |||||
| return pool->bo->iova + pool->stride * query + index * sizeof(uint64_t); | |||||
| } | } | ||||
| VkResult | VkResult | ||||
| tu_cs_emit(cs, A6XX_RB_SAMPLE_COUNT_CONTROL_COPY); | tu_cs_emit(cs, A6XX_RB_SAMPLE_COUNT_CONTROL_COPY); | ||||
| tu_cs_emit_pkt4(cs, REG_A6XX_RB_SAMPLE_COUNT_ADDR_LO, 2); | tu_cs_emit_pkt4(cs, REG_A6XX_RB_SAMPLE_COUNT_ADDR_LO, 2); | ||||
| tu_cs_emit_qw(cs, query_address(pool, query, 1 /* begin */)); | |||||
| tu_cs_emit_qw(cs, query_iova(pool, query, 1 /* begin */)); | |||||
| tu_cs_emit_pkt7(cs, CP_EVENT_WRITE, 1); | tu_cs_emit_pkt7(cs, CP_EVENT_WRITE, 1); | ||||
| tu_cs_emit(cs, ZPASS_DONE); | tu_cs_emit(cs, ZPASS_DONE); | ||||
| tu_bo_list_add(&cmdbuf->bo_list, pool->bo, MSM_SUBMIT_BO_WRITE); | tu_bo_list_add(&cmdbuf->bo_list, pool->bo, MSM_SUBMIT_BO_WRITE); | ||||
| } | } | ||||
| static void | |||||
| emit_end_occlusion_query(struct tu_cmd_buffer *cmdbuf, | |||||
| struct tu_cs *cs, | |||||
| struct tu_query_pool *pool, | |||||
| uint32_t query) { | |||||
| /* Ending an occlusion query happens in a few steps: | |||||
| * 1) Set the query->end to UINT64_MAX. | |||||
| * 2) Set up the SAMPLE_COUNT registers and trigger a CP_EVENT_WRITE to | |||||
| * write the current sample count value into query->end. | |||||
| * 3) Since (2) is asynchronous, wait until query->end is not equal to | |||||
| * UINT64_MAX to set the query's availability bit via CP_WAIT_REG_MEM. | |||||
| */ | |||||
| uint64_t end_iova = query_iova(pool, query, 2 /* end */); | |||||
| tu_cs_reserve_space(cmdbuf->device, cs, 25); | |||||
| tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4); | |||||
| tu_cs_emit_qw(cs, end_iova); | |||||
| tu_cs_emit_qw(cs, 0xffffffffffffffffull); | |||||
| tu_cs_emit_pkt7(cs, CP_WAIT_MEM_WRITES, 0); | |||||
| tu_cs_emit_pkt4(cs, REG_A6XX_RB_SAMPLE_COUNT_CONTROL, 1); | |||||
| tu_cs_emit(cs, A6XX_RB_SAMPLE_COUNT_CONTROL_COPY); | |||||
| tu_cs_emit_pkt4(cs, REG_A6XX_RB_SAMPLE_COUNT_ADDR_LO, 2); | |||||
| tu_cs_emit_qw(cs, end_iova); | |||||
| tu_cs_emit_pkt7(cs, CP_EVENT_WRITE, 1); | |||||
| tu_cs_emit(cs, ZPASS_DONE); | |||||
| tu_cs_emit_pkt7(cs, CP_WAIT_REG_MEM, 6); | |||||
| tu_cs_emit(cs, 0x00000014); // XXX | |||||
| tu_cs_emit_qw(cs, end_iova); | |||||
| tu_cs_emit_qw(cs, 0xffffffffffffffffull); | |||||
| tu_cs_emit(cs, 0x00000010); // XXX | |||||
| tu_cs_emit_pkt7(cs, CP_MEM_WRITE, 4); | |||||
| tu_cs_emit_qw(cs, query_iova(pool, query, 0 /* available */)); | |||||
| tu_cs_emit_qw(cs, 0x1); | |||||
| } | |||||
| void | void | ||||
| tu_CmdEndQuery(VkCommandBuffer commandBuffer, | tu_CmdEndQuery(VkCommandBuffer commandBuffer, | ||||
| VkQueryPool queryPool, | VkQueryPool queryPool, | ||||
| uint32_t query) | uint32_t query) | ||||
| { | { | ||||
| TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, commandBuffer); | |||||
| TU_FROM_HANDLE(tu_query_pool, pool, queryPool); | |||||
| struct tu_cs *cs = &cmdbuf->cs; | |||||
| assert(query < pool->size); | |||||
| switch (pool->type) { | |||||
| case VK_QUERY_TYPE_OCCLUSION: | |||||
| emit_end_occlusion_query(cmdbuf, cs, pool, query); | |||||
| break; | |||||
| case VK_QUERY_TYPE_PIPELINE_STATISTICS: | |||||
| case VK_QUERY_TYPE_TIMESTAMP: | |||||
| unreachable("Unimplemented query type"); | |||||
| default: | |||||
| assert(!"Invalid query type"); | |||||
| } | |||||
| } | } | ||||
| void | void |