blob: 8075f1cbf1d1207f01cd7fbf4ded3f63d609e61a [file] [edit]
/*
* Copyright 2024 Collabora Ltd.
* Copyright 2025 Arm Ltd.
* SPDX-License-Identifier: MIT
*/
#include "compiler/libcl/libcl.h"
#include "compiler/libcl/libcl_vk.h"
#include "genxml/gen_macros.h"
#include "vulkan/panvk_cmd_ts.h"
#if (PAN_ARCH >= 10)
static inline uint64_t
compute_timestamp_query_result(global uint64_t *report_addr,
uint32_t report_count, uint32_t op,
uint32_t sq_mask, bool *available)
{
uint64_t result = 0;
/* Compute min/max and keep track of which streams had non-zero results. */
switch (op) {
case PANVK_QUERY_TS_OP_MIN: {
result = ULONG_MAX;
for (uint32_t i = 0; i < report_count - 1; ++i) {
uint64_t r = report_addr[i];
if (r != 0 && (sq_mask & (1 << i))) {
result = min(result, report_addr[i]);
sq_mask &= ~(1 << i);
}
}
if (result == ULONG_MAX)
result = 0;
break;
}
case PANVK_QUERY_TS_OP_MAX: {
for (uint32_t i = 0; i < report_count - 1; ++i) {
uint64_t r = report_addr[i];
if (r != 0 && (sq_mask & (1 << i))) {
result = max(result, report_addr[i]);
sq_mask &= ~(1 << i);
}
}
break;
}
default:
UNREACHABLE("Invalid timestamp op");
break;
}
/* The result is available if all subqueues have written their value. */
*available = sq_mask == 0;
return result;
}
KERNEL(1)
panlib_copy_ts_query_result(uint64_t pool_addr, global uint32_t *available_addr,
uint32_t query_stride, uint32_t first_query,
uint32_t query_count, uint64_t dst_addr,
uint64_t dst_stride, uint32_t query_type,
uint32_t flags, uint32_t report_count)
{
uint32_t i = cl_global_id.x;
if (i >= query_count)
return;
uintptr_t dst = dst_addr + ((uint64_t)i * dst_stride);
uint32_t query = first_query + i;
global uint64_t *report_addr =
(global uint64_t *)(pool_addr + ((uint64_t)query * query_stride));
uint64_t result = 0;
/* The last report is always metadata. */
uint64_t info = report_addr[report_count - 1];
uint32_t op = panvk_timestamp_info_get_op(info);
uint32_t sq_mask = panvk_timestamp_info_get_sq_mask(info);
bool available = false;
/* If no subqueue should write a result, the query is uninitialized. */
if (sq_mask != 0)
result = compute_timestamp_query_result(report_addr, report_count, op,
sq_mask, &available);
if ((flags & VK_QUERY_RESULT_PARTIAL_BIT) || available)
vk_write_query(dst, 0, flags, result);
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
vk_write_query(dst, 1, flags, available);
}
#endif
#if (PAN_ARCH >= 6 && PAN_ARCH < 10)
static inline void
write_occlusion_query_result(uintptr_t dst_addr, int32_t idx, uint32_t flags,
global uint64_t *report_addr,
uint32_t report_count)
{
uint64_t value = 0;
for (uint32_t i = 0; i < report_count; i++)
value += report_addr[i];
vk_write_query(dst_addr, idx, flags, value);
}
KERNEL(1)
panlib_copy_query_result(uint64_t pool_addr, global uint32_t *available_addr,
uint32_t query_stride, uint32_t first_query,
uint32_t query_count, uint64_t dst_addr,
uint64_t dst_stride, uint32_t query_type,
uint32_t flags, uint32_t report_count)
{
uint32_t i = cl_global_id.x;
if (i >= query_count)
return;
uint32_t query = first_query + i;
uintptr_t dst = dst_addr + ((uint64_t)i * dst_stride);
global uint64_t *report_addr =
(global uint64_t *)(pool_addr + ((uint64_t)query * query_stride));
bool available = available_addr[query];
if ((flags & VK_QUERY_RESULT_PARTIAL_BIT) || available) {
switch (query_type) {
case VK_QUERY_TYPE_OCCLUSION:
write_occlusion_query_result(dst, 0, flags, report_addr, report_count);
break;
default:
UNREACHABLE("Unsupported query type");
break;
}
}
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
vk_write_query(dst, 1, flags, available);
}
}
KERNEL(1)
panlib_clear_query_result(uint64_t pool_addr, global uint32_t *available_addr,
uint32_t query_stride, uint32_t first_query,
uint32_t query_count, uint32_t report_count,
uint32_t availaible_value)
{
uint32_t i = cl_global_id.x;
if (i >= query_count)
return;
uint32_t query = first_query + i;
global uint64_t *report_addr =
(global uint64_t *)(pool_addr + ((uint64_t)query * query_stride));
available_addr[query] = availaible_value;
for (uint32_t i = 0; i < report_count; i++)
report_addr[i] = 0;
}
#endif