radv: Ensure vkGetQueryPoolResults returns in finite-time

When a device lost occured, we were not ensuring that
vkGetQueryPoolResults with VK_QUERY_RESULT_WAIT_BIT was returning.

We could have the caller stuck in our while(...) loop polling the query
atomics forever which violates the finite-time guarantees of this function.

This solves that by adding a timeout to this call to be double the
default TDR timeout for the potential queues relating to this query.

Signed-off-by: Joshua Ashton <joshua@froggi.es>

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Friedrich Vock <friedrich.vock@gmx.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27091>
This commit is contained in:
Joshua Ashton
2024-01-16 14:41:23 +00:00
committed by Marge Bot
parent 907fe6ea62
commit 86954c766f

View File

@@ -1332,6 +1332,27 @@ radv_DestroyQueryPool(VkDevice _device, VkQueryPool _pool, const VkAllocationCal
radv_destroy_query_pool(device, pAllocator, pool);
}
static inline uint64_t
radv_get_rel_timeout_for_query(VkQueryType type)
{
/*
* Certain queries are only possible on certain types of queues
* so pick the TDR timeout of the highest possible type
* and double it to ensure GetQueryPoolResults completes in finite-time.
*
* (compute has longer TDR than gfx, other rings)
*/
switch (type) {
case VK_QUERY_TYPE_OCCLUSION:
case VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT:
case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
case VK_QUERY_TYPE_MESH_PRIMITIVES_GENERATED_EXT:
return radv_get_tdr_timeout_for_ip(AMD_IP_GFX) * 2;
default:
return radv_get_tdr_timeout_for_ip(AMD_IP_COMPUTE) * 2;
}
}
VKAPI_ATTR VkResult VKAPI_CALL
radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags)
@@ -1349,6 +1370,8 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
unsigned query = firstQuery + query_idx;
char *src = pool->ptr + query * pool->stride;
uint32_t available;
bool timed_out = false;
uint64_t atimeout = os_time_get_absolute_timeout(radv_get_rel_timeout_for_query(pool->vk.query_type));
switch (pool->vk.query_type) {
case VK_QUERY_TYPE_TIMESTAMP:
@@ -1361,11 +1384,14 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
do {
value = p_atomic_read(&src64->value);
} while (value == TIMESTAMP_NOT_READY && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (value == TIMESTAMP_NOT_READY && (flags & VK_QUERY_RESULT_WAIT_BIT) &&
!(timed_out = (atimeout < os_time_get_nano())));
available = value != TIMESTAMP_NOT_READY;
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
if (flags & VK_QUERY_RESULT_64_BIT) {
@@ -1395,7 +1421,8 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
do {
start = p_atomic_read(&src64[2 * i].value);
end = p_atomic_read(&src64[2 * i + 1].value);
} while ((!(start & (1ull << 63)) || !(end & (1ull << 63))) && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while ((!(start & (1ull << 63)) || !(end & (1ull << 63))) && (flags & VK_QUERY_RESULT_WAIT_BIT) &&
!(timed_out = (atimeout < os_time_get_nano())));
if (!(start & (1ull << 63)) || !(end & (1ull << 63)))
available = 0;
@@ -1404,7 +1431,9 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
}
}
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
if (flags & VK_QUERY_RESULT_64_BIT) {
@@ -1435,9 +1464,11 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
if (!(p_atomic_read(avail_ptr_start) & 0x80000000) || !(p_atomic_read(avail_ptr_stop) & 0x80000000))
available = 0;
}
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT) && !(timed_out = (atimeout < os_time_get_nano())));
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
const uint64_t *start = (uint64_t *)src;
@@ -1485,9 +1516,11 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
if (!(p_atomic_read(&src64[j].value) & 0x8000000000000000UL))
available = 0;
}
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT) && !(timed_out = (atimeout < os_time_get_nano())));
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
num_primitives_written = p_atomic_read_relaxed(&src64[3].value) - p_atomic_read_relaxed(&src64[1].value);
@@ -1531,9 +1564,11 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
!(p_atomic_read(&src64[5].value) & 0x8000000000000000UL))) {
available = 0;
}
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT) && !(timed_out = (atimeout < os_time_get_nano())));
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
primitive_storage_needed = p_atomic_read_relaxed(&src64[2].value) - p_atomic_read_relaxed(&src64[0].value);
@@ -1563,7 +1598,7 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
for (unsigned i = 0; i < pc_pool->num_passes; ++i)
if (!p_atomic_read(&src64[pool->stride / 8 - i - 1].value))
avail = false;
} while (!avail && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (!avail && (flags & VK_QUERY_RESULT_WAIT_BIT) && !(timed_out = (atimeout < os_time_get_nano())));
available = avail;
@@ -1581,9 +1616,11 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
!(p_atomic_read(&src64[1].value) & 0x8000000000000000UL)) {
available = 0;
}
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT));
} while (!available && (flags & VK_QUERY_RESULT_WAIT_BIT) && !(timed_out = (atimeout < os_time_get_nano())));
if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
if (timed_out)
result = VK_ERROR_DEVICE_LOST;
else if (!available && !(flags & VK_QUERY_RESULT_PARTIAL_BIT))
result = VK_NOT_READY;
ms_prim_gen = p_atomic_read_relaxed(&src64[1].value) - p_atomic_read_relaxed(&src64[0].value);
@@ -1612,6 +1649,9 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
}
}
if (result == VK_ERROR_DEVICE_LOST)
vk_device_set_lost(&device->vk, "GetQueryPoolResults timed out");
return result;
}