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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user