| @@ -48,10 +48,9 @@ struct PACKED occlusion_query_slot { | |||
| /* Returns the IOVA of a given uint64_t field in a given slot of a query | |||
| * 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) { | |||
| return (pool->bo->iova) + (pool->stride * query) + | |||
| (index * sizeof(uint64_t)); | |||
| return pool->bo->iova + pool->stride * query + index * sizeof(uint64_t); | |||
| } | |||
| VkResult | |||
| @@ -167,7 +166,7 @@ emit_begin_occlusion_query(struct tu_cmd_buffer *cmdbuf, | |||
| 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, 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(cs, ZPASS_DONE); | |||
| @@ -202,11 +201,62 @@ tu_CmdBeginQuery(VkCommandBuffer commandBuffer, | |||
| 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 | |||
| tu_CmdEndQuery(VkCommandBuffer commandBuffer, | |||
| VkQueryPool queryPool, | |||
| 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 | |||