aboutsummaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorAlexander Orzechowski <alex@ozal.ski>2023-08-20 20:55:03 -0400
committerAlexander Orzechowski <alex@ozal.ski>2023-08-20 21:12:06 -0400
commit5f6912595e922c30beaf99190634bd1747be8f87 (patch)
treec325b2a9bb68403769dedd7a1bbbe4b1664b0fd1 /render
parentbdc34401ba8e4a59b3464c17fa5acf43ca417e57 (diff)
renderer/vulkan: Defer device lost signal until end of pass
If the compositor were to try to handle a GPU reset within the lost signal (by recreating the renderer) we should avoid referencing renderer resources after the lost signal. This prevents use after free for such compositors.
Diffstat (limited to 'render')
-rw-r--r--render/vulkan/pass.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c
index bfb3628f..505fd36a 100644
--- a/render/vulkan/pass.c
+++ b/render/vulkan/pass.c
@@ -69,6 +69,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
struct wlr_vk_render_buffer *render_buffer = pass->render_buffer;
struct wlr_vk_command_buffer *stage_cb = NULL;
VkSemaphoreSubmitInfoKHR *render_wait = NULL;
+ bool device_lost = false;
if (pass->failed) {
goto error;
@@ -364,11 +365,9 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
VkSubmitInfo2KHR submit_info[] = { stage_submit, render_submit };
VkResult res = renderer->dev->api.vkQueueSubmit2KHR(renderer->dev->queue, 2, submit_info, VK_NULL_HANDLE);
- if (res == VK_ERROR_DEVICE_LOST) {
- wlr_log(WLR_ERROR, "vkQueueSubmit failed with VK_ERROR_DEVICE_LOST");
- wl_signal_emit_mutable(&renderer->wlr_renderer.events.lost, NULL);
- goto error;
- } else if (res != VK_SUCCESS) {
+
+ if (res != VK_SUCCESS) {
+ device_lost = res == VK_ERROR_DEVICE_LOST;
wlr_vk_error("vkQueueSubmit", res);
goto error;
}
@@ -398,6 +397,11 @@ error:
vulkan_reset_command_buffer(render_cb);
wlr_buffer_unlock(render_buffer->wlr_buffer);
free(pass);
+
+ if (device_lost) {
+ wl_signal_emit_mutable(&renderer->wlr_renderer.events.lost, NULL);
+ }
+
return false;
}