summaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nsvg/vkvg_nsvg.c2
-rw-r--r--src/vkvg_context.c27
-rw-r--r--src/vkvg_context_internal.c75
-rw-r--r--src/vkvg_context_internal.h8
-rw-r--r--src/vkvg_device.c79
-rw-r--r--src/vkvg_device_internal.c67
-rw-r--r--src/vkvg_device_internal.h18
-rw-r--r--src/vkvg_fonts.c5
-rw-r--r--src/vkvg_pattern.c4
-rw-r--r--src/vkvg_pattern.h2
-rw-r--r--src/vkvg_surface.c72
-rw-r--r--src/vkvg_surface_internal.c67
-rw-r--r--src/vkvg_surface_internal.h14
13 files changed, 324 insertions, 116 deletions
diff --git a/src/nsvg/vkvg_nsvg.c b/src/nsvg/vkvg_nsvg.c
index 0c34450..681471a 100644
--- a/src/nsvg/vkvg_nsvg.c
+++ b/src/nsvg/vkvg_nsvg.c
@@ -46,7 +46,7 @@ VkvgSurface _svg_load (VkvgDevice dev, NSVGimage* svg) {
surf->width = (uint32_t)svg->width;
surf->height = (uint32_t)svg->height;
- surf->new = true;
+ surf->newSurf = true;
_create_surface_images (surf);
diff --git a/src/vkvg_context.c b/src/vkvg_context.c
index 88249be..0078598 100644
--- a/src/vkvg_context.c
+++ b/src/vkvg_context.c
@@ -62,12 +62,16 @@ void _init_ctx (VkvgContext ctx) {
ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height;
ctx->renderPassBeginInfo.pClearValues = clearValues;
- if (ctx->pSurf->new)
+ LOCK_SURFACE (ctx->pSurf)
+
+ if (ctx->pSurf->newSurf)
ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearAll;
else
ctx->renderPassBeginInfo.renderPass = ctx->dev->renderPass_ClearStencil;
+ ctx->pSurf->newSurf = false;
+
+ UNLOCK_SURFACE (ctx->pSurf);
- ctx->pSurf->new = false;
vkvg_surface_reference (ctx->pSurf);
if (ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT)
@@ -83,6 +87,9 @@ void _init_ctx (VkvgContext ctx) {
ctx->cmdStarted = false;
ctx->curClipState = vkvg_clip_state_none;
ctx->vertCount = ctx->indCount = 0;
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ ctx->timelineStep = 0;
+#endif
}
VkvgContext vkvg_create(VkvgSurface surf)
@@ -149,7 +156,10 @@ VkvgContext vkvg_create(VkvgSurface surf)
//for context to be thread safe, command pool and descriptor pool have to be created in the thread of the context.
ctx->cmdPool = vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+
+#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
ctx->flushFence = vkh_fence_create_signaled ((VkhDevice)ctx->dev);
+#endif
_create_vertices_buff (ctx);
_create_gradient_buff (ctx);
@@ -173,8 +183,9 @@ VkvgContext vkvg_create(VkvgSurface surf)
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)ctx->cmdPool, "CTX Cmd Pool");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[0], "CTX Cmd Buff A");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[1], "CTX Cmd Buff B");
+#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
-
+#endif
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool, "CTX Descriptor Pool");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc, "CTX DescSet SOURCE");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont, "CTX DescSet FONT");
@@ -190,7 +201,7 @@ void vkvg_flush (VkvgContext ctx){
if (ctx->status)
return;
_flush_cmd_buff (ctx);
- _wait_flush_fence (ctx);
+ _wait_ctx_flush_end (ctx);
/*
#ifdef DEBUG
@@ -1272,7 +1283,7 @@ void vkvg_save (VkvgContext ctx){
vkvg_context_save_t* sav = (vkvg_context_save_t*)calloc(1,sizeof(vkvg_context_save_t));
_flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx)) {
+ if (!_wait_ctx_flush_end (ctx)) {
free (sav);
return;
}
@@ -1406,7 +1417,7 @@ void vkvg_restore (VkvgContext ctx){
ctx->pSavedCtxs = sav->pNext;
_flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
ctx->pushConsts = sav->pushConsts;
@@ -1441,7 +1452,7 @@ void vkvg_restore (VkvgContext ctx){
#endif
_flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
}
}
@@ -1483,7 +1494,7 @@ void vkvg_restore (VkvgContext ctx){
VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd));
_wait_and_submit_cmd (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
vkh_image_destroy (savStencil);
}
diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c
index 951e254..bf8078c 100644
--- a/src/vkvg_context_internal.c
+++ b/src/vkvg_context_internal.c
@@ -270,7 +270,7 @@ void _create_vertices_buff (VkvgContext ctx){
ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices);
}
void _resize_vbo (VkvgContext ctx, uint32_t new_size) {
- if (!_wait_flush_fence (ctx))//wait previous cmd if not completed
+ if (!_wait_ctx_flush_end (ctx))//wait previous cmd if not completed
return;
LOG(VKVG_LOG_DBG_ARRAYS, "resize VBO: %d -> ", ctx->sizeVBO);
ctx->sizeVBO = new_size;
@@ -285,7 +285,7 @@ void _resize_vbo (VkvgContext ctx, uint32_t new_size) {
ctx->sizeVBO * sizeof(Vertex), &ctx->vertices);
}
void _resize_ibo (VkvgContext ctx, size_t new_size) {
- if (!_wait_flush_fence (ctx))//wait previous cmd if not completed
+ if (!_wait_ctx_flush_end (ctx))//wait previous cmd if not completed
return;
ctx->sizeIBO = new_size;
uint32_t mod = ctx->sizeIBO % VKVG_IBO_SIZE;
@@ -420,24 +420,64 @@ void _create_cmd_buff (VkvgContext ctx){
void _clear_attachment (VkvgContext ctx) {
}
-bool _wait_flush_fence (VkvgContext ctx) {
+
+bool _wait_ctx_flush_end (VkvgContext ctx) {
LOG(VKVG_LOG_INFO, "CTX: _wait_flush_fence\n");
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ if (vkh_timeline_wait ((VkhDevice)ctx->dev, ctx->pSurf->timeline, ctx->timelineStep) == VK_SUCCESS)
+ return true;
+#else
if (WaitForFences (ctx->dev->vkDev, 1, &ctx->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
return true;
+#endif
LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
ctx->status = VKVG_STATUS_TIMEOUT;
return false;
}
+
+
bool _wait_and_submit_cmd (VkvgContext ctx){
if (!ctx->cmdStarted)//current cmd buff is empty, be aware that wait is also canceled!!
return true;
LOG(VKVG_LOG_INFO, "CTX: _wait_and_submit_cmd\n");
- if (!_wait_flush_fence (ctx))
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ VkvgSurface surf = ctx->pSurf;
+ VkvgDevice dev = surf->dev;
+ //vkh_timeline_wait ((VkhDevice)dev, surf->timeline, ct->timelineStep);
+ if (ctx->pattern && ctx->pattern->type == VKVG_PATTERN_TYPE_SURFACE) {
+ //add source surface timeline sync.
+ VkvgSurface source = (VkvgSurface)ctx->pattern->data;
+ LOCK_SURFACE(surf)
+ LOCK_SURFACE(source)
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined2 (dev->gQueue, &ctx->cmd,
+ (VkSemaphore[2]){surf->timeline,source->timeline},
+ (uint64_t[2]){surf->timelineStep,source->timelineStep},
+ (uint64_t[2]){surf->timelineStep+1,source->timelineStep+1});
+ surf->timelineStep++;
+ source->timelineStep++;
+ ctx->timelineStep = surf->timelineStep;
+ UNLOCK_DEVICE
+ UNLOCK_SURFACE(source)
+ UNLOCK_SURFACE(surf)
+ } else {
+ LOCK_SURFACE(surf)
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined (dev->gQueue, &ctx->cmd, surf->timeline, surf->timelineStep, surf->timelineStep+1);
+ surf->timelineStep++;
+ ctx->timelineStep = surf->timelineStep;
+ UNLOCK_DEVICE
+ UNLOCK_SURFACE(surf)
+ }
+#else
+
+ if (!_wait_ctx_flush_end (ctx))
return false;
- _device_reset_fence(ctx->dev, ctx->flushFence);
+ ResetFences (ctx->dev->vkDev, 1, &ctx->flushFence);
_device_submit_cmd (ctx->dev, &ctx->cmd, ctx->flushFence);
+#endif
if (ctx->cmd == ctx->cmdBuffers[0])
ctx->cmd = ctx->cmdBuffers[1];
@@ -474,7 +514,7 @@ bool _wait_and_submit_cmd (VkvgContext ctx){
//pre flush vertices because of vbo or ibo too small, all vertices except last draw call are flushed
//this function expects a vertex offset > 0
void _flush_vertices_caches_until_vertex_base (VkvgContext ctx) {
- _wait_flush_fence (ctx);
+ _wait_ctx_flush_end (ctx);
memcpy(ctx->vertices.allocInfo.pMappedData, ctx->vertexCache, ctx->curVertOffset * sizeof (Vertex));
memcpy(ctx->indices.allocInfo.pMappedData, ctx->indexCache, ctx->curIndStart * sizeof (VKVG_IBO_INDEX_TYPE));
@@ -491,7 +531,7 @@ void _flush_vertices_caches_until_vertex_base (VkvgContext ctx) {
//copy vertex and index caches to the vbo and ibo vkbuffers used by gpu for drawing
//current running cmd has to be completed to free usage of those
void _flush_vertices_caches (VkvgContext ctx) {
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
memcpy(ctx->vertices.allocInfo.pMappedData, ctx->vertexCache, ctx->vertCount * sizeof (Vertex));
@@ -671,7 +711,7 @@ void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
switch (newPatternType) {
case VKVG_PATTERN_TYPE_SOLID:
_flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
if (lastPat->type == VKVG_PATTERN_TYPE_SURFACE)//unbind current source surface by replacing it with empty texture
_update_descriptor_set (ctx, ctx->dev->emptyImg, ctx->dsSrc);
@@ -686,7 +726,7 @@ void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
if (ctx->cmdStarted){//transition of img without appropriate dependencies in subpass must be done outside renderpass.
_end_render_pass (ctx);
_flush_vertices_caches (ctx);
- }else {
+ } else {
vkh_cmd_begin (ctx->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
ctx->cmdStarted = true;
}
@@ -698,11 +738,9 @@ void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
vkh_cmd_end (ctx->cmd);
_wait_and_submit_cmd (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
- ctx->source = surf->img;
-
VkSamplerAddressMode addrMode = 0;
VkFilter filter = VK_FILTER_NEAREST;
switch (pat->extend) {
@@ -728,10 +766,10 @@ void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
filter = VK_FILTER_NEAREST;
break;
}
- vkh_image_create_sampler (ctx->source, filter, filter,
+ vkh_image_create_sampler (surf->img, filter, filter,
VK_SAMPLER_MIPMAP_MODE_NEAREST, addrMode);
- _update_descriptor_set (ctx, ctx->source, ctx->dsSrc);
+ _update_descriptor_set (ctx, surf->img, ctx->dsSrc);
if (pat->hasMatrix) {
@@ -744,7 +782,7 @@ void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat) {
case VKVG_PATTERN_TYPE_LINEAR:
case VKVG_PATTERN_TYPE_RADIAL:
_flush_cmd_buff (ctx);
- if (!_wait_flush_fence (ctx))
+ if (!_wait_ctx_flush_end (ctx))
return;
if (lastPat && lastPat->type == VKVG_PATTERN_TYPE_SURFACE)
@@ -866,7 +904,10 @@ void _init_descriptor_sets (VkvgContext ctx){
void _release_context_ressources (VkvgContext ctx) {
VkDevice dev = ctx->dev->vkDev;
- _device_destroy_fence (ctx->dev, ctx->flushFence);
+#ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ vkDestroyFence (dev, ctx->flushFence, NULL);
+#endif
+
vkFreeCommandBuffers(dev, ctx->cmdPool, 2, ctx->cmdBuffers);
vkDestroyCommandPool(dev, ctx->cmdPool, NULL);
@@ -1609,7 +1650,7 @@ void _poly_fill (VkvgContext ctx, vec4* bounds){
_flush_vertices_caches (ctx);
vkh_cmd_end (ctx->cmd);
_wait_and_submit_cmd (ctx);
- _wait_flush_fence (ctx);
+ _wait_ctx_flush_end (ctx);
if (ctx->sizeVBO - VKVG_ARRAY_THRESHOLD < ctx->pointCount){
_resize_vbo (ctx, ctx->pointCount + VKVG_ARRAY_THRESHOLD);
_resize_vertex_cache (ctx, ctx->sizeVBO);
diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h
index bd241ec..cff7889 100644
--- a/src/vkvg_context_internal.h
+++ b/src/vkvg_context_internal.h
@@ -131,8 +131,12 @@ typedef struct _vkvg_context_t {
VkvgDevice dev;
VkvgSurface pSurf; //surface bound to context, set on creation of ctx
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ uint64_t timelineStep; //context cmd last submission timeline id.
+#else
VkFence flushFence; //context fence
- VkhImage source; //source of painting operation
+#endif
+ //VkDescriptorImageInfo sourceDescriptor; //Store view/sampler in context
VkCommandPool cmdPool; //local pools ensure thread safety
VkCommandBuffer cmdBuffers[2]; //double cmd buff for context operations
@@ -302,7 +306,7 @@ void _flush_cmd_buff (VkvgContext ctx);
void _ensure_renderpass_is_started (VkvgContext ctx);
void _emit_draw_cmd_undrawn_vertices (VkvgContext ctx);
void _flush_cmd_until_vx_base (VkvgContext ctx);
-bool _wait_flush_fence (VkvgContext ctx);
+bool _wait_ctx_flush_end (VkvgContext ctx);
bool _wait_and_submit_cmd (VkvgContext ctx);
void _update_push_constants (VkvgContext ctx);
void _update_cur_pattern (VkvgContext ctx, VkvgPattern pat);
diff --git a/src/vkvg_device.c b/src/vkvg_device.c
index 11ff1af..adb8abe 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;
@@ -43,6 +59,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
@@ -171,20 +189,36 @@ vkvg_status_t vkvg_get_required_device_extensions (VkPhysicalDevice phy, const c
//https://vulkan.lunarg.com/doc/view/1.2.162.0/mac/1.2-extensions/vkspec.html#VK_KHR_portability_subset
_CHECK_DEV_EXT(VK_KHR_portability_subset);
+ VkPhysicalDeviceFeatures2 phyFeat2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
//ensure feature is implemented by driver.
- VkPhysicalDeviceFeatures2 phyFeat2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
VkPhysicalDeviceScalarBlockLayoutFeatures scalarBlockLayoutSupport = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES};
phyFeat2.pNext = &scalarBlockLayoutSupport;
+#endif
+
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreSupport = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES};
+ timelineSemaphoreSupport.pNext = phyFeat2.pNext;
+ phyFeat2.pNext = &timelineSemaphoreSupport;
+#endif
+
vkGetPhysicalDeviceFeatures2(phy, &phyFeat2);
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
if (!scalarBlockLayoutSupport.scalarBlockLayout) {
- LOG(VKVG_LOG_ERR, "CREATE Device failed, vkvg compiled with VKVG_VK_SCALAR_BLOCK_SUPPORTED and feature is not implemented for physical device.\n");
+ LOG(VKVG_LOG_ERR, "CREATE Device failed, vkvg compiled with VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT and feature is not implemented for physical device.\n");
return VKVG_STATUS_DEVICE_ERROR;
}
_CHECK_DEV_EXT(VK_EXT_scalar_block_layout)
#endif
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ if (!timelineSemaphoreSupport.timelineSemaphore) {
+ LOG(VKVG_LOG_ERR, "CREATE Device failed, VK_SEMAPHORE_TYPE_TIMELINE not supported.\n");
+ return VKVG_STATUS_DEVICE_ERROR;
+ }
+ _CHECK_DEV_EXT(VK_KHR_timeline_semaphore)
+#endif
return VKVG_STATUS_SUCCESS;
}
@@ -198,32 +232,42 @@ const void* vkvg_get_device_requirements (VkPhysicalDeviceFeatures* pEnabledFeat
void* pNext = NULL;
-#ifdef VK_VERSION_1_2
+#ifdef VK_VERSION_1_2_
static VkPhysicalDeviceVulkan12Features enabledFeatures12 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
,.scalarBlockLayout = VK_TRUE
#endif
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ ,.timelineSemaphore = VK_TRUE
+#endif
};
enabledFeatures12.pNext = pNext;
pNext = &enabledFeatures12;
#else
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
static VkPhysicalDeviceScalarBlockLayoutFeaturesEXT scalarBlockFeat = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
,.scalarBlockLayout = VK_TRUE
-#endif
};
scalarBlockFeat.pNext = pNext;
pNext = &scalarBlockFeat;
-
+#endif
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ static VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timelineSemaFeat = {
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR
+ ,.timelineSemaphore = VK_TRUE
+ };
+ timelineSemaFeat.pNext = pNext;
+ pNext = &timelineSemaFeat;
+#endif
#endif
return pNext;
}
-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) {
@@ -354,11 +398,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);
@@ -387,7 +442,7 @@ void vkvg_device_destroy (VkvgDevice dev)
vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
vkDestroyFence (dev->vkDev, dev->fence,NULL);
- //vkFreeCommandBuffers (dev->vkDev, dev->cmdPool, 1, &dev->cmd);
+ vkFreeCommandBuffers (dev->vkDev, dev->cmdPool, 1, &dev->cmd);
vkDestroyCommandPool (dev->vkDev, dev->cmdPool, NULL);
vkh_queue_destroy(dev->gQueue);
diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c
index 86e528b..ab37f2d 100644
--- a/src/vkvg_device_internal.c
+++ b/src/vkvg_device_internal.c
@@ -415,59 +415,62 @@ void _device_wait_idle (VkvgDevice dev) {
}
void _device_wait_and_reset_device_fence (VkvgDevice dev) {
vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
- _device_reset_fence(dev, dev->fence);
+ ResetFences (dev->vkDev, 1, &dev->fence);
}
-void _device_destroy_fence (VkvgDevice dev, VkFence fence) {
- LOCK_DEVICE
-
- if (dev->gQLastFence == fence)
- dev->gQLastFence = VK_NULL_HANDLE;
-
- vkDestroyFence (dev->vkDev, fence, NULL);
-
- UNLOCK_DEVICE
-}
-void _device_reset_fence (VkvgDevice dev, VkFence fence){
+bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx) {
LOCK_DEVICE
- if (dev->gQLastFence == fence)
- dev->gQLastFence = VK_NULL_HANDLE;
-
- ResetFences (dev->vkDev, 1, &fence);
+ 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;
- UNLOCK_DEVICE
-}
-bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx) {
- LOCK_DEVICE
+ dev->cachedContextCount--;
- if (dev->cachedContextCount)
- *pCtx = dev->cachedContext[--dev->cachedContextCount];
- else
- *pCtx = NULL;
+ 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;
LOCK_DEVICE
- 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
}
void _device_submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence) {
LOCK_DEVICE
- if (dev->gQLastFence != VK_NULL_HANDLE)
- WaitForFences (dev->vkDev, 1, &dev->gQLastFence, VK_TRUE, VKVG_FENCE_TIMEOUT);
vkh_cmd_submit (dev->gQueue, cmd, fence);
- dev->gQLastFence = fence;
UNLOCK_DEVICE
}
diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h
index dc44fd3..5503d17 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 2
+#define VKVG_MAX_CACHED_CONTEXT_COUNT 36
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 */
@@ -68,7 +74,6 @@ typedef struct _vkvg_device_t{
mtx_t mutex; /**< protect device access (queue, cahes, ...)from ctxs in separate threads */
bool threadAware; /**< if true, mutex is created and guard device queue and caches access */
VkhQueue gQueue; /**< Vulkan Queue with Graphic flag */
- VkFence gQLastFence;
VkRenderPass renderPass; /**< Vulkan render pass, common for all surfaces */
VkRenderPass renderPass_ClearStencil;/**< Vulkan render pass for first draw with context, stencil has to be cleared */
@@ -106,8 +111,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;
@@ -139,8 +145,6 @@ void _device_wait_idle (VkvgDevice dev);
void _device_wait_and_reset_device_fence(VkvgDevice dev);
void _device_submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence);
-void _device_destroy_fence (VkvgDevice dev, VkFence fence);
-void _device_reset_fence (VkvgDevice dev, VkFence fence);
bool _device_try_get_cached_context (VkvgDevice dev, VkvgContext* pCtx);
void _device_store_context (VkvgContext ctx);
#endif
diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c
index efb2c9a..830d9f3 100644
--- a/src/vkvg_fonts.c
+++ b/src/vkvg_fonts.c
@@ -105,7 +105,7 @@ void _increase_font_tex_array (VkvgDevice dev){
_font_cache_t* cache = dev->fontCache;
vkWaitForFences (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
- _device_reset_fence (dev, cache->uploadFence);
+ ResetFences (dev->vkDev, 1, &cache->uploadFence);
vkResetCommandBuffer(cache->cmd, 0);
@@ -167,7 +167,8 @@ void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n",f->curLine.penX, f->curLine.penY);
vkWaitForFences (dev->vkDev,1,&cache->uploadFence,VK_TRUE,UINT64_MAX);
- _device_reset_fence (dev, cache->uploadFence);
+ ResetFences (dev->vkDev, 1, &cache->uploadFence);
+
vkResetCommandBuffer(cache->cmd,0);
memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
diff --git a/src/vkvg_pattern.c b/src/vkvg_pattern.c
index ffc635e..acefab6 100644
--- a/src/vkvg_pattern.c
+++ b/src/vkvg_pattern.c
@@ -150,7 +150,7 @@ vkvg_status_t vkvg_pattern_add_color_stop (VkvgPattern pat, float offset, float
vkvg_color_t c = {r,g,b,a};
#endif
grad->colors[grad->count] = c;
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
grad->stops[grad->count] = offset;
#else
grad->stops[grad->count].r = offset;
@@ -201,7 +201,7 @@ vkvg_status_t vkvg_pattern_get_color_stop_rgba (VkvgPattern pat, uint32_t index,
vkvg_gradient_t* grad = (vkvg_gradient_t*)pat->data;
if (index >= grad->count)
return VKVG_STATUS_INVALID_INDEX;
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
*offset = grad->stops[index];
#else
*offset = grad->stops[index].r;
diff --git a/src/vkvg_pattern.h b/src/vkvg_pattern.h
index e860012..2ad068d 100644
--- a/src/vkvg_pattern.h
+++ b/src/vkvg_pattern.h
@@ -37,7 +37,7 @@ typedef struct _vkvg_pattern_t {
typedef struct _vkvg_gradient_t {
vkvg_color_t colors[16];
-#ifdef VKVG_VK_SCALAR_BLOCK_SUPPORTED
+#ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT
float stops[16];
#else
vec4 stops[16];
diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c
index 05dc8dd..701e9c4 100644
--- a/src/vkvg_surface.c
+++ b/src/vkvg_surface.c
@@ -30,6 +30,31 @@
#include "vkh_image.h"
#define max(x,y)
+void _transition_surf_images (VkvgSurface surf) {
+ LOCK_SURFACE(surf)
+ VkvgDevice dev = surf->dev;
+
+ //_surface_wait_cmd (surf);
+
+ vkh_cmd_begin (surf->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+ VkhImage imgMs = surf->imgMS;
+ if (imgMs != NULL)
+ vkh_image_set_layout(surf->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+
+ vkh_image_set_layout(surf->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT,
+ VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ vkh_image_set_layout (surf->cmd, surf->stencil, VK_IMAGE_ASPECT_STENCIL_BIT,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
+ vkh_cmd_end (surf->cmd);
+
+ _surface_submit_cmd (surf);
+
+ UNLOCK_SURFACE(surf)
+}
void vkvg_surface_clear (VkvgSurface surf) {
if (surf->status)
return;
@@ -42,10 +67,12 @@ VkvgSurface vkvg_surface_create (VkvgDevice dev, uint32_t width, uint32_t height
surf->width = MAX(1, width);
surf->height = MAX(1, height);
- surf->new = true;//used to clear all attacments on first render pass
+ surf->newSurf = true;//used to clear all attacments on first render pass
_create_surface_images (surf);
+ _transition_surf_images (surf);
+
surf->status = VKVG_STATUS_SUCCESS;
vkvg_device_reference (surf->dev);
return surf;
@@ -71,7 +98,9 @@ VkvgSurface vkvg_surface_create_for_VkhImage (VkvgDevice dev, void* vkhImg) {
_create_surface_secondary_images (surf);
_create_framebuffer (surf);
- _clear_surface (surf, VK_IMAGE_ASPECT_STENCIL_BIT);
+
+ _transition_surf_images (surf);
+ //_clear_surface (surf, VK_IMAGE_ASPECT_STENCIL_BIT);
surf->status = VKVG_STATUS_SUCCESS;
vkvg_device_reference (surf->dev);
@@ -110,9 +139,7 @@ VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img,
memcpy (buff.allocInfo.pMappedData, img, imgSize);
- VkCommandBuffer cmd = dev->cmd;
-
- _device_wait_and_reset_device_fence (dev);
+ VkCommandBuffer cmd = surf->cmd;
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
@@ -148,15 +175,13 @@ VkvgSurface vkvg_surface_create_from_bitmap (VkvgDevice dev, unsigned char* img,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
- //don't reset fence after completion as this is the last cmd. (signaled idle fence)
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ _surface_submit_cmd (surf);//lock surface?
vkvg_buffer_destroy (&buff);
vkh_image_destroy (stagImg);
- surf->new = false;
+ surf->newSurf = false;
//create tmp context with rendering pipeline to create the multisample img
VkvgContext ctx = vkvg_create (surf);
@@ -212,6 +237,7 @@ void vkvg_surface_destroy(VkvgSurface surf)
}
UNLOCK_SURFACE(surf)
+ vkDestroyCommandPool(surf->dev->vkDev, surf->cmdPool, NULL);
vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL);
if (!surf->img->imported)
@@ -223,6 +249,12 @@ void vkvg_surface_destroy(VkvgSurface surf)
if (surf->dev->threadAware)
mtx_destroy (&surf->mutex);
+#if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ vkDestroySemaphore (surf->dev->vkDev, surf->timeline, NULL);
+#else
+ vkDestroyFence (surf->dev->vkDev, surf->flushFence, NULL);
+#endif
+
vkvg_device_destroy (surf->dev);
free(surf);
}
@@ -304,9 +336,7 @@ vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path){
VMA_MEMORY_USAGE_GPU_ONLY,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- VkCommandBuffer cmd = dev->cmd;
- _device_wait_and_reset_device_fence (dev);
-
+ VkCommandBuffer cmd = surf->cmd;
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
@@ -326,7 +356,8 @@ vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path){
vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
+
+ _surface_submit_cmd (surf);
VkhImage stagImgLinear = stagImg;
@@ -341,7 +372,6 @@ vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path){
.dstOffset = {0},
.extent = {(int32_t)surf->width, (int32_t)surf->height, 1}
};
- _device_wait_and_reset_device_fence (dev);
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
vkh_image_set_layout (cmd, stagImgLinear, VK_IMAGE_ASPECT_COLOR_BIT,
@@ -355,12 +385,11 @@ vkvg_status_t vkvg_surface_write_to_png (VkvgSurface surf, const char* path){
vkh_image_get_vkimage (stagImgLinear), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cpy);
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ _surface_submit_cmd (surf);
+
vkh_image_destroy (stagImg);
- } else
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ }
void* img = vkh_image_map (stagImgLinear);
@@ -395,8 +424,7 @@ vkvg_status_t vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* con
VMA_MEMORY_USAGE_GPU_TO_CPU,
VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT);
- VkCommandBuffer cmd = dev->cmd;
- _device_wait_and_reset_device_fence (dev);
+ VkCommandBuffer cmd = surf->cmd;
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
vkh_image_set_layout (cmd, stagImg, VK_IMAGE_ASPECT_COLOR_BIT,
@@ -417,8 +445,8 @@ vkvg_status_t vkvg_surface_write_to_memory (VkvgSurface surf, unsigned char* con
vkh_image_get_vkimage (stagImg), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit, VK_FILTER_NEAREST);
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+
+ _surface_submit_cmd (surf);
uint64_t stride = vkh_image_get_stride(stagImg);
uint32_t dest_stride = surf->width * 4;
diff --git a/src/vkvg_surface_internal.c b/src/vkvg_surface_internal.c
index ffa5983..263489b 100644
--- a/src/vkvg_surface_internal.c
+++ b/src/vkvg_surface_internal.c
@@ -20,15 +20,15 @@
* THE SOFTWARE.
*/
-#include "vkvg_surface_internal.h"
#include "vkvg_device_internal.h"
+#include "vkvg_surface_internal.h"
#include "vkh_image.h"
+#include "vkh_queue.h"
void _explicit_ms_resolve (VkvgSurface surf){
- VkvgDevice dev = surf->dev;
- VkCommandBuffer cmd = dev->cmd;
+ LOCK_SURFACE (surf)
- _device_wait_and_reset_device_fence (dev);
+ VkCommandBuffer cmd = surf->cmd;
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
vkh_image_set_layout (cmd, surf->imgMS, VK_IMAGE_ASPECT_COLOR_BIT,
@@ -53,15 +53,16 @@ void _explicit_ms_resolve (VkvgSurface surf){
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
+ _surface_submit_cmd (surf);
+
+ UNLOCK_SURFACE (surf)
}
void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect)
{
- VkvgDevice dev = surf->dev;
- VkCommandBuffer cmd = dev->cmd;
+ LOCK_SURFACE (surf)
- _device_wait_and_reset_device_fence (dev);
+ VkCommandBuffer cmd = surf->cmd;
vkh_cmd_begin (cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
@@ -101,7 +102,9 @@ void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect)
}
vkh_cmd_end (cmd);
- _device_submit_cmd (dev, &cmd, dev->fence);
+ _surface_submit_cmd (surf);
+
+ UNLOCK_SURFACE (surf)
}
void _create_surface_main_image (VkvgSurface surf){
@@ -186,5 +189,51 @@ VkvgSurface _create_surface (VkvgDevice dev, VkFormat format) {
surf->format = format;
if (dev->threadAware)
mtx_init (&surf->mutex, mtx_plain);
+ surf->cmdPool = vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+ vkh_cmd_buffs_create((VkhDevice)dev, surf->cmdPool,VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &surf->cmd);
+
+#if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ surf->timeline = vkh_timeline_create ((VkhDevice)dev, 0);
+#else
+ surf->flushFence = vkh_fence_create ((VkhDevice)dev);
+#endif
+
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd");
+#endif
+
return surf;
}
+//if fence sync, surf mutex must be locked.
+/*bool _surface_wait_cmd (VkvgSurface surf) {
+ LOG(VKVG_LOG_INFO, "SURF: _surface__wait_flush_fence\n");
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ if (vkh_timeline_wait ((VkhDevice)surf->dev, surf->timeline, surf->timelineStep) == VK_SUCCESS)
+ return true;
+#else
+ if (WaitForFences (surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS) {
+ ResetFences (surf->dev->vkDev, 1, &surf->flushFence);
+ return true;
+ }
+#endif
+ LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
+ surf->status = VKVG_STATUS_TIMEOUT;
+ return false;
+}*/
+//surface mutex must be locked to call this method, locking to guard also the surf->cmd local buffer usage.
+void _surface_submit_cmd (VkvgSurface surf) {
+ VkvgDevice dev = surf->dev;
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ LOCK_DEVICE
+ vkh_cmd_submit_timelined (dev->gQueue, &surf->cmd, surf->timeline, surf->timelineStep, surf->timelineStep+1);
+ surf->timelineStep++;
+ UNLOCK_DEVICE
+ vkh_timeline_wait ((VkhDevice)dev, surf->timeline, surf->timelineStep);
+#else
+ LOCK_DEVICE
+ vkh_cmd_submit (surf->dev->gQueue, &surf->cmd, surf->flushFence);
+ UNLOCK_DEVICE
+ WaitForFences (surf->dev->vkDev, 1, &surf->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT);
+ ResetFences (surf->dev->vkDev, 1, &surf->flushFence);
+#endif
+}
diff --git a/src/vkvg_surface_internal.h b/src/vkvg_surface_internal.h
index 79b64e3..5cc47c6 100644
--- a/src/vkvg_surface_internal.h
+++ b/src/vkvg_surface_internal.h
@@ -37,8 +37,17 @@ typedef struct _vkvg_surface_t {
VkhImage img;
VkhImage imgMS;
VkhImage stencil;
- bool new;
+ VkCommandPool cmdPool; //local pools ensure thread safety
+ VkCommandBuffer cmd; //surface local command buffer.
+ bool newSurf;
mtx_t mutex;
+#ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
+ VkSemaphore timeline; /**< Timeline semaphore */
+ uint64_t timelineStep;
+#else
+ VkFence flushFence; //unsignaled idle.
+#endif
+
}vkvg_surface;
#define LOCK_SURFACE(surf) \
@@ -55,4 +64,7 @@ void _create_surface_secondary_images (VkvgSurface surf);
void _create_framebuffer (VkvgSurface surf);
void _create_surface_images (VkvgSurface surf);
VkvgSurface _create_surface (VkvgDevice dev, VkFormat format);
+
+void _surface_submit_cmd (VkvgSurface surf);
+//bool _surface_wait_cmd (VkvgSurface surf);
#endif