]> O.S.I.I.S - jp/vkvg.git/commitdiff
test threadctx threadctxtests
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Wed, 26 Jan 2022 21:01:48 +0000 (22:01 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Wed, 26 Jan 2022 21:01:48 +0000 (22:01 +0100)
14 files changed:
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_context_internal.h
src/vkvg_device.c
src/vkvg_device_internal.c
src/vkvg_device_internal.h
src/vkvg_fonts.c
src/vkvg_fonts.h
src/vkvg_surface.c
src/vkvg_surface_internal.c
src/vkvg_sync_context_internal.c [new file with mode: 0644]
src/vkvg_sync_context_internal.h [new file with mode: 0644]
tests/multithreading/multithreaded.c
vkh

index 152bbb17578cc68678b24924086bdd502e9b8e9f..981ad55c9402f5722fe6635065a5ee6186e379f9 100644 (file)
@@ -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);
 
index c191c4e98d55106af6720728cef8325a0ac73fa7..39471b829bf47453691d78359323cd135340dc48 100644 (file)
@@ -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];
index 6747d7d8e19de1944d633236bdc8160f33dbfbb2..bb3ab7fb017860c7c7d216a76cea8da143b3b7b9 100644 (file)
@@ -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
index da5820dcd5f39c2f38856311a6e4c5e6730928da..6acb1c977a5103698af3f30d8e9d497f2423f673 100644 (file)
 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
index d66df4c74bca88e231ec34418246c2d61adee041..8319630d4886a672adba5115468fdb74d22dbd15 100644 (file)
@@ -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) {
index 376b9c28ae125f73af71c786b8d22b94a38c34ea..be1d1b445e9afaec124130880da8d7e6b7421670 100644 (file)
@@ -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
index d4ed5fd5246aa107b2845a13edb5d5cd2df6ec38..8863c53256921c26c63404f7e50f4bbe80dd454f 100644 (file)
@@ -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;
index 3a2be102d1f5878ed8e13f03dd78d8273d7fb658..c84a2998bf8d399385995fbf691076cc4d3f625f 100644 (file)
@@ -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*/
index 89ff376411a96122dbb416f783e3fd68cc553888..9055b52ff039cd45256e0c8be55cfc9bf234ebe0 100644 (file)
@@ -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;
index a8cc8ff6bece6cb3d9d144ff275c1eb419fad416..307845a9b395b2509888fe9a17b3d3d9c7088276 100644 (file)
@@ -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 (file)
index 0000000..b74292e
--- /dev/null
@@ -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 (file)
index 0000000..d1581b0
--- /dev/null
@@ -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
index cc4aa0a35ac33d3d4245fd8de0a2802d2ece5296..2b2afc9195097dd5b51f4bb4d04fea999cdfd5ea 100644 (file)
@@ -1,7 +1,7 @@
 #include "test.h"
 #include "tinycthread.h"
 
-#define THREAD_COUNT 2
+#define THREAD_COUNT 8
 
 
 static int finishedThreadCount = 0;
@@ -19,16 +19,14 @@ void drawRandomRect (VkvgContext ctx, float s) {
 }
 void _before_submit (void* data) {
        mtx_lock((mtx_t*)data);
+       printf("sumbit  0x%lx\n", thrd_current());
 }
 void _after_submit (void* data) {
+       printf("release 0x%lx\n", thrd_current());
        mtx_unlock((mtx_t*)data);
 }
 
 int drawRectsThread () {
-       mtx_t gQMutex;
-       mtx_init (&gQMutex, mtx_plain);
-       vkvg_device_set_queue_guards (device, _before_submit, _after_submit, &gQMutex);
-
        VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
        VkvgContext ctx = vkvg_create(s);
        for (uint32_t i=0; i<test_size; i++) {
@@ -49,12 +47,15 @@ int drawRectsThread () {
        mtx_unlock(&mutex);
 
        vkvg_surface_destroy (s);
-       vkvg_device_set_queue_guards (device, NULL, NULL, NULL);
-       mtx_destroy (&gQMutex);
        return 0;
 }
 void fixedSizeRects(){
+       printf("==>main 0x%lx\n", thrd_current());
+       mtx_t gQMutex;
+       mtx_init (&gQMutex, mtx_plain);
+       vkvg_device_set_queue_guards (device, _before_submit, _after_submit, &gQMutex);
        thrd_t threads[THREAD_COUNT];
+
        finishedThreadCount = 0;
        mtx_init (&mutex,mtx_plain);
        for (uint32_t i=0; i<THREAD_COUNT; i++) {
@@ -66,6 +67,10 @@ void fixedSizeRects(){
                thrd_sleep(&ts, NULL);
 
        mtx_destroy(&mutex);
+
+       vkvg_device_set_queue_guards (device, NULL, NULL, NULL);
+       mtx_destroy (&gQMutex);
+       printf("------- 0x%lx\n", thrd_current());
 }
 
 int main(int argc, char *argv[]) {
diff --git a/vkh b/vkh
index e448f9f0e10fbc1d0a62ce471c73880d207e7d66..4439697af748a6101294cd30d2e7facc4eeaf568 160000 (submodule)
--- a/vkh
+++ b/vkh
@@ -1 +1 @@
-Subproject commit e448f9f0e10fbc1d0a62ce471c73880d207e7d66
+Subproject commit 4439697af748a6101294cd30d2e7facc4eeaf568