blob: 3b80c6601f5dda45cbc5d029389838491bbad557 [file]
/*
* Copyright 2024 Alyssa Rosenzweig
* Copyright 2024 Valve Corporation
* Copyright 2022 Collabora Ltd. and Red Hat Inc.
* SPDX-License-Identifier: MIT
*/
#include "compiler/libcl/libcl.h"
#include "compiler/libcl/libcl_vk.h"
#include "query.h"
static inline global uint64_t *
query_report(global uint64_t *results, global uint16_t *oq_index,
uint reports_per_query, uint query)
{
/* For occlusion queries, results[] points to the device global heap. We
* need to remap indices according to the query pool's allocation.
*/
uint result_index = oq_index ? oq_index[query] : query;
return results + (result_index * reports_per_query);
}
KERNEL(32)
libagx_copy_query(global uint32_t *availability, global uint64_t *results,
global uint16_t *oq_index, uint64_t dst_addr,
uint64_t dst_stride, uint32_t first_query,
VkQueryResultFlagBits flags, uint16_t reports_per_query)
{
uint i = cl_global_id.x;
uint64_t dst = dst_addr + (((uint64_t)i) * dst_stride);
uint32_t query = first_query + i;
bool available;
if (availability)
available = availability[query];
else
available = (results[query] != LIBAGX_QUERY_UNAVAILABLE);
global uint64_t *report =
query_report(results, oq_index, reports_per_query, query);
if (available || (flags & VK_QUERY_RESULT_PARTIAL_BIT)) {
for (unsigned i = 0; i < reports_per_query; ++i) {
vk_write_query(dst, i, flags, report[i]);
}
}
if (flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
vk_write_query(dst, reports_per_query, flags, available);
}
}
/**
* Goes through a series of consecutive query indices in the given pool,
* setting all element values to 0 and emitting them as available.
*/
KERNEL(32)
libagx_reset_query(global uint32_t *availability, global uint64_t *results,
global uint16_t *oq_index, uint32_t first_query,
uint16_t reports_per_query, int set_available)
{
uint32_t query = first_query + cl_global_id.x;
uint64_t value = 0;
if (availability) {
availability[query] = set_available;
} else {
value = set_available ? 0 : LIBAGX_QUERY_UNAVAILABLE;
}
global uint64_t *report =
query_report(results, oq_index, reports_per_query, query);
/* XXX: is this supposed to happen on the begin? */
for (unsigned j = 0; j < reports_per_query; ++j) {
report[j] = value;
}
}
/* TODO: Share with Gallium... */
enum pipe_query_value_type {
PIPE_QUERY_TYPE_I32,
PIPE_QUERY_TYPE_U32,
PIPE_QUERY_TYPE_I64,
PIPE_QUERY_TYPE_U64,
};
KERNEL(1)
libagx_copy_query_gl(global uint64_t *query, global uint64_t *dest,
ushort value_type, ushort bool_size)
{
uint64_t value = *query;
if (bool_size == 4) {
value = (uint32_t)value;
}
if (bool_size) {
value = value != 0;
}
if (value_type <= PIPE_QUERY_TYPE_U32) {
global uint32_t *dest32 = (global uint32_t *)dest;
bool u32 = (value_type == PIPE_QUERY_TYPE_U32);
*dest32 = u32 ? convert_uint_sat(value) : convert_int_sat((int64_t)value);
} else {
*dest = value;
}
}
KERNEL(4)
libagx_copy_xfb_counters(constant struct libagx_xfb_counter_copy *push)
{
unsigned i = cl_local_id.x;
*(push->dest[i]) = push->src[i] ? *(push->src[i]) : 0;
}
KERNEL(1)
libagx_increment_statistic(global uint32_t *statistic, uint32_t delta)
{
*statistic += delta;
}
KERNEL(1)
libagx_increment_cs_invocations(global uint *grid, global uint32_t *statistic,
uint32_t local_size_threads)
{
*statistic += local_size_threads * grid[0] * grid[1] * grid[2];
}
KERNEL(32)
libagx_write_u32s(constant struct libagx_imm_write *p)
{
uint id = cl_global_id.x;
*(p[id].address) = p[id].value;
}
/*
* We set the source as volatile since the caching situation around timestamps
* is a bit unclear. It might not be necessary but - absent hardware/firmware
* documentation - this gives me peace of mind.
*/
KERNEL(1)
libagx_copy_timestamp(global uint64_t *dest, volatile global uint64_t *src)
{
*dest = *src;
}
KERNEL(1)
libagx_write_u32(global uint32_t *address, uint32_t value)
{
*address = value;
}