#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
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.
*
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)
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);
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;
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
}
-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) {
}
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);
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) {
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;
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
#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;
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 */
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;