From: Jean-Philippe Bruyère Date: Fri, 4 Mar 2022 06:48:04 +0000 (+0100) Subject: store context in device context cache per thread X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=a5d0d810d6e07383ac0fe44a554b9733dc41d871;p=jp%2Fvkvg.git store context in device context cache per thread --- diff --git a/include/vkvg.h b/include/vkvg.h index c38b59f..769a330 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -89,6 +89,7 @@ extern "C" { #define VKVG_LOG_INFO_VBO 0x00000020 #define VKVG_LOG_INFO_IBO 0x00000040 #define VKVG_LOG_INFO_VAO (VKVG_LOG_INFO_VBO|VKVG_LOG_INFO_IBO) +#define VKVG_LOG_THREAD 0x00000080 #define VKVG_LOG_DBG_ARRAYS 0x00001000 #define VKVG_LOG_FULL 0xffffffff @@ -553,7 +554,17 @@ void vkvg_matrix_get_scale (const vkvg_matrix_t *matrix, float *sx, float *sy); vkvg_public void vkvg_device_set_thread_aware (VkvgDevice dev, uint32_t thread_awayre); - +vkvg_public +/** + * @brief Set maximum cached context count. + * + * The context cache stored destroyed contexts per thread to speed-up new context creation. + * To disable context cache, call this method with maxCount=0. + * + * @param dev A valid vkvg device pointer. + * @param maxCount The maximum count of saved contexts for fast context instanciation. + */ +void vkvg_device_set_context_cache_size (VkvgDevice dev, uint32_t maxCount); /** * @brief Create a new vkvg device. * diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 6e5d125..dfcd76e 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -62,12 +62,17 @@ void _init_ctx (VkvgContext ctx) { ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height; ctx->renderPassBeginInfo.pClearValues = clearValues; + LOCK_SURFACE (ctx->pSurf) + if (ctx->pSurf->new) ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll; else ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil; ctx->pSurf->new = false; + + UNLOCK_SURFACE (ctx->pSurf); + vkvg_surface_reference (ctx->pSurf); if (ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT) diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 415037a..2eb20d3 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -873,7 +873,7 @@ void _release_context_ressources (VkvgContext ctx) { VkDescriptorSet dss[] = {ctx->dsFont, ctx->dsSrc, ctx->dsGrad}; vkFreeDescriptorSets (dev, ctx->descriptorPool, 3, dss); - vkDestroyDescriptorPool (dev, ctx->descriptorPool,NULL); + vkDestroyDescriptorPool (dev, ctx->descriptorPool, NULL); vkvg_buffer_destroy (&ctx->uboGrad); vkvg_buffer_destroy (&ctx->indices); diff --git a/src/vkvg_device.c b/src/vkvg_device.c index 4a266cc..eb50287 100644 --- a/src/vkvg_device.c +++ b/src/vkvg_device.c @@ -31,6 +31,22 @@ if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \ enabledExts[enabledExtsCount++] = #ext; \ } +void vkvg_device_set_context_cache_size (VkvgDevice dev, uint32_t maxCount) { + if (maxCount == dev->cachedContextMaxCount) + return; + + dev->cachedContextMaxCount = maxCount; + + _cached_ctx* cur = dev->cachedContextLast; + while (cur && dev->cachedContextCount > dev->cachedContextMaxCount) { + _release_context_ressources (cur->ctx); + _cached_ctx* prev = cur; + cur = cur->pNext; + free (prev); + dev->cachedContextCount--; + } + dev->cachedContextLast = cur; +} void _device_init (VkvgDevice dev, VkInstance inst, VkPhysicalDevice phy, VkDevice vkdev, uint32_t qFamIdx, uint32_t qIndex, VkSampleCountFlags samples, bool deferredResolve) { dev->instance = inst; dev->hdpi = 72; @@ -40,6 +56,8 @@ void _device_init (VkvgDevice dev, VkInstance inst, VkPhysicalDevice phy, VkDevi dev->vkDev = vkdev; dev->phy = phy; + dev->cachedContextMaxCount = VKVG_MAX_CACHED_CONTEXT_COUNT; + #if VKVG_DBG_STATS dev->debug_stats = (vkvg_debug_stats_t) {0}; #endif @@ -205,7 +223,7 @@ const void* vkvg_get_device_requirements (VkPhysicalDeviceFeatures* pEnabledFeat } -VkvgDevice vkvg_device_create(VkSampleCountFlags samples, bool deferredResolve) { +VkvgDevice vkvg_device_create (VkSampleCountFlags samples, bool deferredResolve) { LOG(VKVG_LOG_INFO, "CREATE Device\n"); VkvgDevice dev = (vkvg_device*)calloc(1,sizeof(vkvg_device)); if (!dev) { @@ -337,11 +355,22 @@ void vkvg_device_destroy (VkvgDevice dev) } UNLOCK_DEVICE - while (dev->cachedContextCount > 0) - _release_context_ressources (dev->cachedContext[--dev->cachedContextCount]); + + if (dev->cachedContextCount > 0) { + _cached_ctx* cur = dev->cachedContextLast; + while (cur) { + _release_context_ressources (cur->ctx); + _cached_ctx* prev = cur; + cur = cur->pNext; + free (prev); + } + } + LOG(VKVG_LOG_INFO, "DESTROY Device\n"); + vkDeviceWaitIdle (dev->vkDev); + vkh_image_destroy (dev->emptyImg); vkDestroyDescriptorSetLayout (dev->vkDev, dev->dslGrad,NULL); diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c index cbec2c4..87784c2 100644 --- a/src/vkvg_device_internal.c +++ b/src/vkvg_device_internal.c @@ -414,8 +414,10 @@ void _device_wait_idle (VkvgDevice dev) { vkDeviceWaitIdle (dev->vkDev); } void _device_wait_and_reset_device_fence (VkvgDevice dev) { + LOCK_DEVICE vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX); _device_reset_fence(dev, dev->fence); + UNLOCK_DEVICE } void _device_destroy_fence (VkvgDevice dev, VkFence fence) { @@ -441,14 +443,33 @@ void _device_reset_fence (VkvgDevice dev, VkFence fence){ bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx) { LOCK_DEVICE - if (dev->cachedContextCount) - *pCtx = dev->cachedContext[--dev->cachedContextCount]; - else - *pCtx = NULL; - + if (dev->cachedContextCount) { + thrd_t curThread = thrd_current (); + _cached_ctx* prev = NULL; + _cached_ctx* cur = dev->cachedContextLast; + while (cur) { + if (thrd_equal (cur->thread, curThread)) { + if (prev) + prev->pNext = cur->pNext; + else + dev->cachedContextLast = cur->pNext; + + dev->cachedContextCount--; + + LOG(VKVG_LOG_THREAD,"get cached context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread, dev->cachedContextCount); + + *pCtx = cur->ctx; + free (cur); + UNLOCK_DEVICE + return true; + } + prev = cur; + cur = cur->pNext; + } + } + *pCtx = NULL; UNLOCK_DEVICE - - return *pCtx != NULL; + return false; } void _device_store_context (VkvgContext ctx) { VkvgDevice dev = ctx->dev; @@ -457,7 +478,17 @@ void _device_store_context (VkvgContext ctx) { if (dev->gQLastFence == ctx->flushFence) dev->gQLastFence = VK_NULL_HANDLE; - dev->cachedContext[dev->cachedContextCount++] = ctx; + + _cached_ctx* cur = (_cached_ctx*)calloc(1, sizeof(_cached_ctx)); + cur->ctx = ctx; + cur->thread = thrd_current (); + cur->pNext = dev->cachedContextLast; + + dev->cachedContextLast = cur; + dev->cachedContextCount++; + + LOG(VKVG_LOG_THREAD,"store context: %p, thd:%lu cached ctx: %d\n", cur->ctx, cur->thread, dev->cachedContextCount); + ctx->references++; UNLOCK_DEVICE diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h index f776880..eba61a1 100644 --- a/src/vkvg_device_internal.h +++ b/src/vkvg_device_internal.h @@ -30,7 +30,7 @@ #define STENCIL_CLIP_BIT 0x2 #define STENCIL_ALL_BIT 0x3 -#define VKVG_MAX_CACHED_CONTEXT_COUNT 0 +#define VKVG_MAX_CACHED_CONTEXT_COUNT 2 extern PFN_vkCmdBindPipeline CmdBindPipeline; extern PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets; @@ -53,7 +53,13 @@ extern PFN_vkWaitForFences WaitForFences; extern PFN_vkResetFences ResetFences; extern PFN_vkResetCommandBuffer ResetCommandBuffer; -typedef struct _vkvg_device_t{ +typedef struct _cached_ctx{ + thrd_t thread; + VkvgContext ctx; + struct _cached_ctx* pNext; +} _cached_ctx; + +typedef struct _vkvg_device_t { VkDevice vkDev; /**< Vulkan Logical Device */ VkPhysicalDeviceMemoryProperties phyMemProps; /**< Vulkan Physical device memory properties */ VkPhysicalDevice phy; /**< Vulkan Physical device */ @@ -106,8 +112,9 @@ typedef struct _vkvg_device_t{ VkvgContext lastCtx; /**< last element of double linked list of context, used to trigger font caching system update on all contexts*/ - int32_t cachedContextCount; - VkvgContext cachedContext[VKVG_MAX_CACHED_CONTEXT_COUNT]; + int32_t cachedContextMaxCount; /**< Maximum context cache element count.*/ + int32_t cachedContextCount; /**< Current context cache element count.*/ + _cached_ctx* cachedContextLast; /**< Last element of single linked list of saved context for fast reuse.*/ #ifdef VKVG_WIRED_DEBUG VkPipeline pipelineWired;