summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Halase <jordan@halase.me>2019-11-11 12:46:36 -0600
committerJordan Halase <jordan@halase.me>2019-11-11 12:46:36 -0600
commita512576efc870650b2d3fa018891b2a1cdf4b613 (patch)
treef4e7732950c510b01fe03cadf0a3ef53ee50e79f
parentf5c35ec2ae33a8a752487869a6f9a53f0f5ce5e1 (diff)
Automatically collect swapchain garbageHEADmaster
-rwxr-xr-xmain.c30
1 files changed, 19 insertions, 11 deletions
diff --git a/main.c b/main.c
index 3903579..2e38bf2 100755
--- a/main.c
+++ b/main.c
@@ -1600,24 +1600,32 @@ static bool canDestroySwapchain(const struct RenderVulkan *vk,
return !notReady;
}
-/* FIXME: Race condition! Swapchains cannot be destroyed until they are done
- * being rendered to.
+/** Collects old swapchains only, leaving the latest one intact. This will
+ * only delete the swapchains not in use.
*/
void rvkCollectSwapchainGarbage(struct RenderVulkan *vk)
{
- struct SwapchainVulkan *old, *pp = vk->swapchain;
- uint32_t count = 0;
- if (pp && (pp)->old) {
- for(pp = (pp)->old; pp; pp = old) {
- old = (pp)->old;
- rvkDestroySwapchain(vk, pp);
+ struct SwapchainVulkan *old, *sc, *lag = vk->swapchain;
+ uint32_t count = 0, del = 0;
+ if (lag && lag->old) {
+ for(sc = lag->old; sc; sc = old) {
+ old = sc->old;
+ if (canDestroySwapchain(vk, sc)) {
+ rvkDestroySwapchain(vk, sc);
+ lag->old = old;
+ ++del;
+ } else {
+ lag = lag->old;
+ }
++count;
}
- vk->swapchain->old = NULL;
}
- printf("Collected %d retired swapchains\n", count);
+ if (count > 1) {
+ printf("Collected %d/%d retired swapchains\n", del, count);
+ }
}
+/** This must not be called until all swapchains are no longer in use. */
void rvkDestroyAllSwapchains(struct RenderVulkan *vk)
{
struct SwapchainVulkan *swapchain, *old;
@@ -1821,6 +1829,7 @@ PuglStatus onDisplay(PuglView *view)
vk->dev->vkQueuePresentKHR(vk->graphicsQueue, &presentInfo);
+ rvkCollectSwapchainGarbage(vk);
if (args.continuous) ++framesDrawn;
return PUGL_SUCCESS;
}
@@ -1864,7 +1873,6 @@ PuglStatus onEvent(PuglView *view, const PuglEvent *e)
break;
case 'c':
// Manually collect swapchain garbage
- vk->dev->vkDeviceWaitIdle(vk->device);
rvkCollectSwapchainGarbage(vk);
break;
}