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:
@@ -1332,6 +1332,27 @@ radv_DestroyQueryPool(VkDevice _device, VkQueryPool _pool, const VkAllocationCal
|
|||||||
radv_destroy_query_pool(device, pAllocator, pool);
|
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
|
VKAPI_ATTR VkResult VKAPI_CALL
|
||||||
radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
|
radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
|
||||||
size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags)
|
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;
|
unsigned query = firstQuery + query_idx;
|
||||||
char *src = pool->ptr + query * pool->stride;
|
char *src = pool->ptr + query * pool->stride;
|
||||||
uint32_t available;
|
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) {
|
switch (pool->vk.query_type) {
|
||||||
case VK_QUERY_TYPE_TIMESTAMP:
|
case VK_QUERY_TYPE_TIMESTAMP:
|
||||||
@@ -1361,11 +1384,14 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
value = p_atomic_read(&src64->value);
|
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;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
if (flags & VK_QUERY_RESULT_64_BIT) {
|
if (flags & VK_QUERY_RESULT_64_BIT) {
|
||||||
@@ -1395,7 +1421,8 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
|
|||||||
do {
|
do {
|
||||||
start = p_atomic_read(&src64[2 * i].value);
|
start = p_atomic_read(&src64[2 * i].value);
|
||||||
end = p_atomic_read(&src64[2 * i + 1].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)))
|
if (!(start & (1ull << 63)) || !(end & (1ull << 63)))
|
||||||
available = 0;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
if (flags & VK_QUERY_RESULT_64_BIT) {
|
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))
|
if (!(p_atomic_read(avail_ptr_start) & 0x80000000) || !(p_atomic_read(avail_ptr_stop) & 0x80000000))
|
||||||
available = 0;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
const uint64_t *start = (uint64_t *)src;
|
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))
|
if (!(p_atomic_read(&src64[j].value) & 0x8000000000000000UL))
|
||||||
available = 0;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
num_primitives_written = p_atomic_read_relaxed(&src64[3].value) - p_atomic_read_relaxed(&src64[1].value);
|
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))) {
|
!(p_atomic_read(&src64[5].value) & 0x8000000000000000UL))) {
|
||||||
available = 0;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
primitive_storage_needed = p_atomic_read_relaxed(&src64[2].value) - p_atomic_read_relaxed(&src64[0].value);
|
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)
|
for (unsigned i = 0; i < pc_pool->num_passes; ++i)
|
||||||
if (!p_atomic_read(&src64[pool->stride / 8 - i - 1].value))
|
if (!p_atomic_read(&src64[pool->stride / 8 - i - 1].value))
|
||||||
avail = false;
|
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;
|
available = avail;
|
||||||
|
|
||||||
@@ -1581,9 +1616,11 @@ radv_GetQueryPoolResults(VkDevice _device, VkQueryPool queryPool, uint32_t first
|
|||||||
!(p_atomic_read(&src64[1].value) & 0x8000000000000000UL)) {
|
!(p_atomic_read(&src64[1].value) & 0x8000000000000000UL)) {
|
||||||
available = 0;
|
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;
|
result = VK_NOT_READY;
|
||||||
|
|
||||||
ms_prim_gen = p_atomic_read_relaxed(&src64[1].value) - p_atomic_read_relaxed(&src64[0].value);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user