summaryrefslogtreecommitdiffstatsci
path: root/src
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2022-01-26 22:01:48 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2022-01-26 22:01:48 +0100
commit19abdef1af4b28e40ba6b994ea22e92b7dde1d8f (patch)
treeffdc7f4d10e351ee1856158cc14ac0277542aa1b /src
parent88c83b6b9b465a670f4989bbe21bd2e5f9eb2dd0 (diff)
test threadctxthreadctxtests
Diffstat (limited to 'src')
-rw-r--r--src/vkvg_context.c11
-rw-r--r--src/vkvg_context_internal.c12
-rw-r--r--src/vkvg_context_internal.h4
-rw-r--r--src/vkvg_device.c27
-rw-r--r--src/vkvg_device_internal.c37
-rw-r--r--src/vkvg_device_internal.h11
-rw-r--r--src/vkvg_fonts.c21
-rw-r--r--src/vkvg_fonts.h3
-rw-r--r--src/vkvg_surface.c16
-rw-r--r--src/vkvg_surface_internal.c4
-rw-r--r--src/vkvg_sync_context_internal.c90
-rw-r--r--src/vkvg_sync_context_internal.h47
12 files changed, 225 insertions, 58 deletions
diff --git a/src/vkvg_context.c b/src/vkvg_context.c
index 152bbb1..981ad55 100644
--- a/src/vkvg_context.c
+++ b/src/vkvg_context.c
@@ -128,7 +128,8 @@ VkvgContext vkvg_create(VkvgSurface surf)
return NULL;
}
- ctx->flushFence = vkh_fence_create_signaled ((VkhDevice)dev);
+ _sync_context_init ((VkhDevice)dev, &ctx->syncCtx);
+
//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);
@@ -154,7 +155,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");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->syncCtx.fence, "CTX Flush Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)ctx->syncCtx.signals[0], "CTX Semaphore A");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)ctx->syncCtx.signals[1], "CTX Semaphore B");
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");
@@ -235,10 +238,12 @@ void vkvg_destroy (VkvgContext ctx)
#endif
- vkDestroyFence (dev, ctx->flushFence,NULL);
+
vkFreeCommandBuffers(dev, ctx->cmdPool, 2, ctx->cmdBuffers);
vkDestroyCommandPool(dev, ctx->cmdPool, NULL);
+ _sync_context_clear (&ctx->syncCtx);
+
VkDescriptorSet dss[] = {ctx->dsFont,ctx->dsSrc, ctx->dsGrad};
vkFreeDescriptorSets (dev, ctx->descriptorPool, 3, dss);
diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c
index c191c4e..39471b8 100644
--- a/src/vkvg_context_internal.c
+++ b/src/vkvg_context_internal.c
@@ -410,7 +410,7 @@ void _clear_attachment (VkvgContext ctx) {
}
bool _wait_flush_fence (VkvgContext ctx) {
LOG(VKVG_LOG_INFO, "CTX: _wait_flush_fence\n");
- if (WaitForFences (ctx->pSurf->dev->vkDev, 1, &ctx->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
+ if (WaitForFences (ctx->pSurf->dev->vkDev, 1, &ctx->syncCtx.fence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
return true;
LOG(VKVG_LOG_DEBUG, "CTX: _wait_flush_fence timeout\n");
ctx->status = VKVG_STATUS_TIMEOUT;
@@ -418,7 +418,7 @@ bool _wait_flush_fence (VkvgContext ctx) {
}
void _reset_flush_fence (VkvgContext ctx) {
LOG(VKVG_LOG_INFO, "CTX: _reset_flush_fence\n");
- ResetFences (ctx->pSurf->dev->vkDev, 1, &ctx->flushFence);
+ ResetFences (ctx->pSurf->dev->vkDev, 1, &ctx->syncCtx.fence);
}
bool _wait_and_submit_cmd (VkvgContext ctx){
if (!ctx->cmdStarted)//current cmd buff is empty, be aware that wait is also canceled!!
@@ -426,11 +426,11 @@ bool _wait_and_submit_cmd (VkvgContext ctx){
LOG(VKVG_LOG_INFO, "CTX: _wait_and_submit_cmd\n");
- if (!_wait_flush_fence (ctx))
+ /*if (!_wait_flush_fence (ctx))
return false;
- _reset_flush_fence(ctx);
-
- _submit_cmd (ctx->pSurf->dev, &ctx->cmd, ctx->flushFence);
+ _reset_flush_fence(ctx);*/
+ _sync_context_wait_and_reset (&ctx->syncCtx, VKVG_FENCE_TIMEOUT);
+ _submit_cmd (ctx->pSurf->dev, &ctx->cmd, &ctx->syncCtx);
if (ctx->cmd == ctx->cmdBuffers[0])
ctx->cmd = ctx->cmdBuffers[1];
diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h
index 6747d7d..bb3ab7f 100644
--- a/src/vkvg_context_internal.h
+++ b/src/vkvg_context_internal.h
@@ -27,6 +27,7 @@
#include "vkvg_buff.h"
#include "vkh.h"
#include "vkvg_fonts.h"
+#include "vkvg_sync_context_internal.h"
#if VKVG_RECORDING
#include "recording/vkvg_record_internal.h"
@@ -130,7 +131,8 @@ typedef struct _vkvg_context_t {
uint32_t references; //reference count
VkvgSurface pSurf; //surface bound to context, set on creation of ctx
- VkFence flushFence; //context fence
+ vkvg_sync_context syncCtx;
+
VkhImage source; //source of painting operation
VkCommandPool cmdPool; //local pools ensure thread safety
diff --git a/src/vkvg_device.c b/src/vkvg_device.c
index da5820d..6acb1c9 100644
--- a/src/vkvg_device.c
+++ b/src/vkvg_device.c
@@ -29,14 +29,15 @@
if (vkh_phyinfo_try_get_extension_properties(pi, #ext, NULL)) \
enabledExts[enabledExtsCount++] = #ext; \
}
+
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->vdpi = 72;
- dev->samples= samples;
+ dev->instance = inst;
+ dev->hdpi = 72;
+ dev->vdpi = 72;
+ dev->samples = samples;
+ dev->vkDev = vkdev;
+ dev->phy = phy;
dev->deferredResolve = deferredResolve;
- dev->vkDev = vkdev;
- dev->phy = phy;
#if VKVG_DBG_STATS
dev->debug_stats = (vkvg_debug_stats_t) {0};
@@ -69,8 +70,8 @@ void _device_init (VkvgDevice dev, VkInstance inst, VkPhysicalDevice phy, VkDevi
dev->cmdPool= vkh_cmd_pool_create ((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
dev->cmd = vkh_cmd_buff_create ((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
- dev->fence = vkh_fence_create_signaled ((VkhDevice)dev);
+ _sync_context_init ((VkhDevice)dev, &dev->syncCtx);
_create_pipeline_cache (dev);
_init_fonts_cache (dev);
if (dev->deferredResolve || dev->samples == VK_SAMPLE_COUNT_1_BIT){
@@ -90,7 +91,9 @@ void _device_init (VkvgDevice dev, VkInstance inst, VkPhysicalDevice phy, VkDevi
#if defined(DEBUG) && defined (VKVG_DBG_UTILS)
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)dev->cmdPool, "Device Cmd Pool");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)dev->cmd, "Device Cmd Buff");
- vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->fence, "Device Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->syncCtx.fence, "Device Fence");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)dev->syncCtx.signals[0], "Device Semaphore A");
+ vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)dev->syncCtx.signals[1], "Device Semaphore B");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass, "RP load img/stencil");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearStencil, "RP clear stencil");
vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll, "RP clear all");
@@ -286,9 +289,9 @@ void vkvg_device_destroy (VkvgDevice dev)
vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearStencil, NULL);
vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearAll, NULL);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ _sync_context_wait (&dev->syncCtx, UINT64_MAX);
+ _sync_context_clear (&dev->syncCtx);
- vkDestroyFence (dev->vkDev, dev->fence,NULL);
vkFreeCommandBuffers (dev->vkDev, dev->cmdPool, 1, &dev->cmd);
vkDestroyCommandPool (dev->vkDev, dev->cmdPool, NULL);
@@ -328,8 +331,8 @@ void vkvg_device_get_dpy (VkvgDevice dev, int* hdpy, int* vdpy) {
*vdpy = dev->vdpi;
}
void vkvg_device_set_queue_guards (VkvgDevice dev, vkvg_queue_guard before_submit, vkvg_queue_guard after_submit, void* user_data) {
- dev->gQBeforeSubmitGuard = before_submit;
- dev->gQAfterSubmitGuard = after_submit;
+ dev->gQLockGuard = before_submit;
+ dev->gQUnlockGuard = after_submit;
dev->gQGuardUserData = user_data;
}
#if VKVG_DBG_STATS
diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c
index d66df4c..8319630 100644
--- a/src/vkvg_device_internal.c
+++ b/src/vkvg_device_internal.c
@@ -423,16 +423,35 @@ void _wait_idle (VkvgDevice dev) {
vkDeviceWaitIdle (dev->vkDev);
}
void _wait_and_reset_device_fence (VkvgDevice dev) {
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
- vkResetFences (dev->vkDev, 1, &dev->fence);
+ vkWaitForFences (dev->vkDev, 1, &dev->syncCtx.fence, VK_TRUE, UINT64_MAX);
+ vkResetFences (dev->vkDev, 1, &dev->syncCtx.fence);
}
-void _submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence) {
- if (dev->gQBeforeSubmitGuard)
- dev->gQBeforeSubmitGuard (dev->gQGuardUserData);
- vkh_cmd_submit (dev->gQueue, cmd, fence);
- if (dev->gQAfterSubmitGuard)
- dev->gQAfterSubmitGuard (dev->gQGuardUserData);
+void _submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, vkvg_sync_context* sync) {
+ if (dev->gQLockGuard)
+ dev->gQLockGuard (dev->gQGuardUserData);
+
+ _sync_context_dbg_print("sync:", sync);
+ _sync_context_dbg_print("signaled:", dev->gQLastSignaledSync);
+ //_sync_context_dbg_print("awaited :", dev->gQLastAwaitedSync);
+
+ if (dev->gQLastSignaledSync)
+ vkh_cmd_submit_with_semaphores(dev->gQueue, cmd,
+ dev->gQLastSignaledSync->signals[!dev->gQLastSignaledSync->nextSubmIdx],
+ sync->signals[sync->nextSubmIdx], sync->fence);
+ else
+ vkh_cmd_submit_with_semaphores(dev->gQueue, cmd, VK_NULL_HANDLE, sync->signals[sync->nextSubmIdx], sync->fence);
+
+ sync->nextSubmIdx ^= true;
+
+ if (dev->gQLastSignaledSync) {
+ dev->gQLastSignaledSync->awaitedBy = sync;
+ sync->awaiting = dev->gQLastSignaledSync;
+ }
+ dev->gQLastSignaledSync = sync;
+
+ if (dev->gQUnlockGuard)
+ dev->gQUnlockGuard (dev->gQGuardUserData);
}
bool _init_function_pointers (VkvgDevice dev) {
@@ -476,7 +495,7 @@ void _create_empty_texture (VkvgDevice dev, VkFormat format, VkImageTiling tilin
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
vkh_cmd_end (dev->cmd);
- _submit_cmd (dev, &dev->cmd, dev->fence);
+ _submit_cmd (dev, &dev->cmd, &dev->syncCtx);
}
void _check_best_image_tiling (VkvgDevice dev, VkFormat format) {
diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h
index 376b9c2..be1d1b4 100644
--- a/src/vkvg_device_internal.h
+++ b/src/vkvg_device_internal.h
@@ -25,6 +25,7 @@
#include "vkvg_internal.h"
#include "vkvg.h"
#include "vkvg_fonts.h"
+#include "vkvg_sync_context_internal.h"
#define STENCIL_FILL_BIT 0x1
#define STENCIL_CLIP_BIT 0x2
@@ -63,8 +64,8 @@ typedef struct _vkvg_device_t{
VkFormat pngStagFormat; /**< Supported vulkan image format png write staging img */
VkImageTiling pngStagTiling; /**< tiling for the blit operation */
- vkvg_queue_guard gQBeforeSubmitGuard;
- vkvg_queue_guard gQAfterSubmitGuard;
+ vkvg_queue_guard gQLockGuard;
+ vkvg_queue_guard gQUnlockGuard;
void* gQGuardUserData;
VkhQueue gQueue; /**< Vulkan Queue with Graphic flag */
@@ -75,7 +76,9 @@ typedef struct _vkvg_device_t{
uint32_t references; /**< Reference count, prevent destroying device if still in use */
VkCommandPool cmdPool; /**< Global command pool for processing on surfaces without context */
VkCommandBuffer cmd; /**< Global command buffer */
- VkFence fence; /**< this fence is kept signaled when idle, wait and reset are called before each recording. */
+ vkvg_sync_context syncCtx; /**< device cmds sync context */
+ //vkvg_sync_context* gQLastAwaitedSync; /**< Last sync context whose signal semaphore is waited in cmd submission */
+ vkvgSync gQLastSignaledSync; /**< Last sync context submitted with signal semaphore */
VkPipeline pipe_OVER; /**< default operator */
VkPipeline pipe_SUB;
@@ -124,5 +127,5 @@ void _createDescriptorSetLayout (VkvgDevice dev);
void _flush_all_contexes (VkvgDevice dev);
void _wait_idle (VkvgDevice dev);
void _wait_and_reset_device_fence (VkvgDevice dev);
-void _submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, VkFence fence);
+void _submit_cmd (VkvgDevice dev, VkCommandBuffer* cmd, vkvg_sync_context *sync);
#endif
diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c
index d4ed5fd..8863c53 100644
--- a/src/vkvg_fonts.c
+++ b/src/vkvg_fonts.c
@@ -70,7 +70,7 @@ void _init_fonts_cache (VkvgDevice dev){
vkh_image_create_descriptor (cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
- cache->uploadFence = vkh_fence_create((VkhDevice)dev);
+ _sync_context_init ((VkhDevice)dev,&cache->uploadSync);
uint32_t buffLength = FONT_PAGE_SIZE*FONT_PAGE_SIZE*cache->texPixelSize;
@@ -88,7 +88,7 @@ void _init_fonts_cache (VkvgDevice dev){
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _submit_cmd (dev, &cache->cmd, cache->uploadFence);
+ _submit_cmd (dev, &cache->cmd, &cache->uploadSync);
cache->hostBuff = (uint8_t*)malloc(buffLength);
cache->pensY = (int*)calloc(cache->texLength, sizeof(int));
@@ -103,9 +103,8 @@ void _increase_font_tex_array (VkvgDevice dev){
_font_cache_t* cache = dev->fontCache;
- vkWaitForFences (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
- vkResetCommandBuffer(cache->cmd, 0);
- vkResetFences (dev->vkDev, 1, &cache->uploadFence);
+ _sync_context_wait_and_reset (&cache->uploadSync, UINT64_MAX);
+ vkResetCommandBuffer (cache->cmd, 0);
uint8_t newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
VkhImage newImg = vkh_tex2d_array_create ((VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE,
@@ -139,8 +138,8 @@ void _increase_font_tex_array (VkvgDevice dev){
VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _submit_cmd (dev, &cache->cmd, cache->uploadFence);
- vkWaitForFences (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
+ _submit_cmd (dev, &cache->cmd, &cache->uploadSync);
+ _sync_context_wait (&cache->uploadSync, UINT64_MAX);
cache->pensY = (int*)realloc(cache->pensY, newSize * sizeof(int));
void* tmp = memset (&cache->pensY[cache->texLength],0,FONT_CACHE_INIT_LAYERS*sizeof(int));
@@ -215,11 +214,10 @@ void _destroy_font_cache (VkvgDevice dev){
free(cache->fonts);
free(cache->pensY);
-
vkvg_buffer_destroy (&cache->buff);
vkh_image_destroy (cache->texture);
//vkFreeCommandBuffers(dev->vkDev,dev->cmdPool, 1, &cache->cmd);
- vkDestroyFence (dev->vkDev,cache->uploadFence,NULL);
+ _sync_context_clear (&cache->uploadSync);
#ifdef VKVG_USE_FREETYPE
FT_Done_FreeType(cache->library);
#endif
@@ -240,9 +238,8 @@ void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
return;
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);
+ _sync_context_wait_and_reset(&cache->uploadSync, UINT64_MAX);
vkResetCommandBuffer(cache->cmd,0);
- vkResetFences (dev->vkDev,1,&cache->uploadFence);
memcpy(cache->buff.allocInfo.pMappedData, cache->hostBuff, (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
@@ -268,7 +265,7 @@ void _flush_chars_to_tex (VkvgDevice dev, _vkvg_font_t* f) {
VK_CHECK_RESULT(vkEndCommandBuffer(cache->cmd));
- _submit_cmd (dev, &cache->cmd, cache->uploadFence);
+ _submit_cmd (dev, &cache->cmd, &cache->uploadSync);
f->curLine.penX += cache->stagingX;
cache->stagingX = 0;
diff --git a/src/vkvg_fonts.h b/src/vkvg_fonts.h
index 3a2be10..c84a299 100644
--- a/src/vkvg_fonts.h
+++ b/src/vkvg_fonts.h
@@ -64,6 +64,7 @@
#include "vkvg_buff.h"
#include "vkh.h"
#include "vectors.h"
+#include "vkvg_sync_context_internal.h"
//texture coordinates of one character in font cache array texture.
@@ -142,7 +143,7 @@ typedef struct {
uint8_t texPixelSize; /* Size in byte of a single pixel in a font texture */
uint8_t texLength; /* layer count of 2d array texture, starts with FONT_CACHE_INIT_LAYERS count and increased when needed */
int* pensY; /* array of current y pen positions for each texture in cache 2d array */
- VkFence uploadFence; /* Signaled when upload is finished */
+ vkvg_sync_context uploadSync; /* upload sync context */
_vkvg_font_identity_t* fonts; /* Loaded fonts structure array */
int32_t fontsCount; /* Loaded fonts array count*/
diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c
index 89ff376..9055b52 100644
--- a/src/vkvg_surface.c
+++ b/src/vkvg_surface.c
@@ -148,10 +148,10 @@ 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);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
//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);
+ WaitForFences (dev->vkDev, 1, &dev->syncCtx.fence, VK_TRUE, UINT64_MAX);
vkvg_buffer_destroy (&buff);
vkh_image_destroy (stagImg);
@@ -298,7 +298,7 @@ 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);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
VkhImage stagImgLinear = stagImg;
@@ -327,12 +327,12 @@ 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);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ vkWaitForFences (dev->vkDev, 1, &dev->syncCtx.fence, VK_TRUE, UINT64_MAX);
vkh_image_destroy (stagImg);
} else
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ vkWaitForFences (dev->vkDev, 1, &dev->syncCtx.fence, VK_TRUE, UINT64_MAX);
void* img = vkh_image_map (stagImgLinear);
@@ -386,8 +386,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);
- _submit_cmd (dev, &cmd, dev->fence);
- vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
+ vkWaitForFences (dev->vkDev, 1, &dev->syncCtx.fence, VK_TRUE, UINT64_MAX);
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 a8cc8ff..307845a 100644
--- a/src/vkvg_surface_internal.c
+++ b/src/vkvg_surface_internal.c
@@ -53,7 +53,7 @@ void _explicit_ms_resolve (VkvgSurface surf){
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
vkh_cmd_end (cmd);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
}
void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect)
@@ -101,7 +101,7 @@ void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect)
}
vkh_cmd_end (cmd);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
}
void _create_surface_main_image (VkvgSurface surf){
diff --git a/src/vkvg_sync_context_internal.c b/src/vkvg_sync_context_internal.c
new file mode 100644
index 0000000..b74292e
--- /dev/null
+++ b/src/vkvg_sync_context_internal.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018-2022 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vkvg_sync_context_internal.h"
+#include "vkvg_device_internal.h"
+
+void _sync_context_init (VkvgDevice dev, vkvg_sync_context* ctx) {
+ VkhDevice d = (VkhDevice)dev;
+ ctx->dev = dev;
+ ctx->fence = vkh_fence_create_signaled (d);
+ ctx->signals[0] = vkh_semaphore_create (d);
+ ctx->signals[1] = vkh_semaphore_create (d);
+}
+void _sync_context_clear (vkvgSync ctx) {
+ if (ctx->dev->gQLockGuard)
+ ctx->dev->gQLockGuard (ctx->dev->gQGuardUserData);
+
+ _sync_context_dbg_print("cleared:", ctx);
+ //_sync_context_dbg_print("signaled:", ctx->dev->gQLastSignaledSync);
+ //_sync_context_dbg_print("awaited :", ctx->dev->gQLastAwaitedSync);
+
+ /*if (ctx->dev->gQLastAwaitedSync == ctx) {
+ vkWaitForFences(ctx->dev->vkDev, 1, &ctx->dev->gQLastAwaitedSync->fence, VK_TRUE, UINT64_MAX);
+ if (ctx->dev->gQLastSignaledSync)
+ vkWaitForFences(ctx->dev->vkDev, 1, &ctx->dev->gQLastSignaledSync->fence, VK_TRUE, UINT64_MAX);
+ ctx->dev->gQLastAwaitedSync = NULL;
+ ctx->dev->gQLastSignaledSync = NULL;
+ }*/
+ if (ctx->dev->gQLastSignaledSync == ctx)
+ ctx->dev->gQLastSignaledSync = NULL;
+
+ VkDevice dev = ctx->dev->vkDev;
+
+ if (ctx->awaiting) {
+ ctx->awaiting->awaitedBy = NULL;
+ ctx->awaiting = NULL;
+ }
+
+ if (ctx->awaitedBy) {
+ vkWaitForFences(dev, 1, &ctx->awaitedBy->fence, VK_TRUE, UINT64_MAX);
+ ctx->awaitedBy = NULL;
+ }
+ vkWaitForFences(dev, 1, &ctx->fence, VK_TRUE, UINT64_MAX);
+
+ vkDestroyFence (dev, ctx->fence, NULL);
+ vkDestroySemaphore (dev, ctx->signals[0], NULL);
+ vkDestroySemaphore (dev, ctx->signals[1], NULL);
+
+ if (ctx->dev->gQUnlockGuard)
+ ctx->dev->gQUnlockGuard (ctx->dev->gQGuardUserData);
+}
+VkResult _sync_context_wait (vkvgSync ctx, uint64_t timeout) {
+ return vkWaitForFences (ctx->dev->vkDev, 1, &ctx->fence, VK_TRUE, timeout);
+}
+VkResult _sync_context_wait_and_reset (vkvgSync ctx, uint64_t timeout) {
+ VkResult res = vkWaitForFences (ctx->dev->vkDev, 1, &ctx->fence, VK_TRUE, timeout);
+ if (ctx->dev->gQLockGuard)
+ ctx->dev->gQLockGuard (ctx->dev->gQGuardUserData);
+ _sync_context_dbg_print("reset:", ctx);
+ vkResetFences (ctx->dev->vkDev, 1, &ctx->fence);
+ if (ctx->dev->gQUnlockGuard)
+ ctx->dev->gQUnlockGuard (ctx->dev->gQGuardUserData);
+ return res;
+}
+void _sync_context_dbg_print (const char* label, vkvg_sync_context* ctx) {
+ if (ctx)
+ printf("\t\t%20s ctx: %16p sigA: %16p sigB: %16p\n", label, ctx, ctx->signals[0], ctx->signals[1]);
+ else
+ printf("\t\t%20s ctx: %16p\n", label, ctx);
+}
+
diff --git a/src/vkvg_sync_context_internal.h b/src/vkvg_sync_context_internal.h
new file mode 100644
index 0000000..d1581b0
--- /dev/null
+++ b/src/vkvg_sync_context_internal.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2022 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef VKVG_SYNC_CONTEXT_INTERNAL_H
+#define VKVG_SYNC_CONTEXT_INTERNAL_H
+
+#include "vkvg_internal.h"
+#include "vkvg.h"
+#include "vkh.h"
+
+typedef struct _vkvg_sync_context* vkvgSync;
+
+typedef struct _vkvg_sync_context {
+ VkvgDevice dev;
+ VkFence fence; // this fence is kept signaled when idle, wait and reset are called before each recording.
+ VkSemaphore signals[2]; // dual signal semaphore couple with the fence guard ensure sync in multithreaded.
+ bool nextSubmIdx; // switch between signal[0] and [1], index of the next sema to use as signal
+
+ vkvgSync awaitedBy;
+ vkvgSync awaiting;
+}vkvg_sync_context;
+
+void _sync_context_init (VkvgDevice dev, vkvg_sync_context* ctx);
+void _sync_context_clear (vkvgSync ctx);
+VkResult _sync_context_wait (vkvgSync ctx, uint64_t timeout);
+VkResult _sync_context_wait_and_reset (vkvgSync ctx, uint64_t timeout);
+
+void _sync_context_dbg_print (const char *label, vkvg_sync_context* ctx);
+#endif