]> O.S.I.I.S - jp/vkvg.git/commitdiff
buggy font cache mutex guarding, multithreaded tests
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Fri, 18 Feb 2022 14:49:55 +0000 (15:49 +0100)
committerj-p <jp_bruyere@hotmail.com>
Fri, 18 Feb 2022 20:09:23 +0000 (21:09 +0100)
12 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
tests/multithreading/multithreaded.c
tests/multithreading/multithreaded2.c
tests/multithreading/threaded_create_surf.c [new file with mode: 0644]
vkh

index dca954e8e23acc53277c23037bb9a3f36ce33777..ed073b95d8c2f4b780eda502533437c18d139bf7 100644 (file)
@@ -132,10 +132,10 @@ VkvgContext vkvg_create(VkvgSurface surf)
 
        _init_ctx (ctx);
 
-       ctx->points     = (vec2*)malloc (VKVG_VBO_SIZE*sizeof(vec2));
-       ctx->pathes     = (uint32_t*)malloc (VKVG_PATHES_SIZE*sizeof(uint32_t));
-       ctx->vertexCache = (Vertex*)malloc(ctx->sizeVertices * sizeof(Vertex));
-       ctx->indexCache = (VKVG_IBO_INDEX_TYPE*)malloc(ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE));
+       ctx->points                     = (vec2*)malloc (VKVG_VBO_SIZE * sizeof(vec2));
+       ctx->pathes                     = (uint32_t*)malloc (VKVG_PATHES_SIZE * sizeof(uint32_t));
+       ctx->vertexCache        = (Vertex*)malloc (ctx->sizeVertices * sizeof(Vertex));
+       ctx->indexCache         = (VKVG_IBO_INDEX_TYPE*)malloc (ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE));
 
        if (!ctx->points || !ctx->pathes || !ctx->vertexCache || !ctx->indexCache) {
                dev->status = VKVG_STATUS_NO_MEMORY;
@@ -159,6 +159,7 @@ VkvgContext vkvg_create(VkvgSurface surf)
        _create_cmd_buff                (ctx);
        _createDescriptorPool   (ctx);
        _init_descriptor_sets   (ctx);
+       _font_cache_update_context_descset (ctx);
        _update_descriptor_set  (ctx, ctx->dev->fontCache->texture, ctx->dsFont);
        _update_descriptor_set  (ctx, surf->dev->emptyImg, ctx->dsSrc);
        _update_gradient_desc_set(ctx);
index c9fc67b52e5bcf548cbc4f8753d669b91040a7c2..b1bd258b052fb244ad64c11cf38a50ca978ebcfd 100644 (file)
@@ -424,8 +424,8 @@ bool _wait_and_submit_cmd (VkvgContext ctx){
 
        if (!_wait_flush_fence (ctx))
                return false;
-       _device_reset_fence(ctx->pSurf->dev, ctx->flushFence);
-       _device_submit_cmd (ctx->pSurf->dev, &ctx->cmd, ctx->flushFence);
+       _device_reset_fence(ctx->dev, ctx->flushFence);
+       _device_submit_cmd (ctx->dev, &ctx->cmd, ctx->flushFence);
 
        if (ctx->cmd == ctx->cmdBuffers[0])
                ctx->cmd = ctx->cmdBuffers[1];
@@ -591,7 +591,7 @@ void _start_cmd_for_render_pass (VkvgContext ctx) {
        LOG(VKVG_LOG_INFO, "START RENDER PASS: ctx = %p\n", ctx);
        vkh_cmd_begin (ctx->cmd,VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
 
-       if (ctx->pSurf->img->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL){
+       if (ctx->pSurf->img->layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL || ctx->dev->threadAware){
                VkhImage imgMs = ctx->pSurf->imgMS;
                if (imgMs != NULL)
                        vkh_image_set_layout(ctx->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT,
@@ -870,6 +870,7 @@ void _release_context_ressources (VkvgContext ctx) {
        free(ctx->vertexCache);
        free(ctx->indexCache);
 
+       vkh_image_destroy         (ctx->fontCacheImg);
        //TODO:check this for source counter
        //vkh_image_destroy       (ctx->source);
 
index cf01d589e1c6e3f9cd7b66d6997625858b0b9522..71017be1459729a13c88125208194512276a9e13 100644 (file)
@@ -126,22 +126,25 @@ typedef struct _vkvg_context_save_t {
 typedef struct _vkvg_context_t {
        //VkvgContext                   pPrev;          //double linked list of contexts
        //VkvgContext                   pNext;
-       uint32_t                        references; //reference count
+       uint32_t                        references;             //reference count
 
        VkvgDevice                      dev;
-       VkvgSurface                     pSurf;          //surface bound to context, set on creation of ctx
-       VkFence                         flushFence; //context fence
-       VkhImage                        source;         //source of painting operation
-
-       VkCommandPool           cmdPool;        //local pools ensure thread safety
-       VkCommandBuffer         cmdBuffers[2];//double cmd buff for context operations
-       VkCommandBuffer         cmd;            //current recording buffer
-       bool                            cmdStarted; //prevent flushing empty renderpass
-       bool                            pushCstDirty;//prevent pushing to gpu if not requested
-       VkDescriptorPool        descriptorPool;//one pool per thread
-       VkDescriptorSet         dsFont;         //fonts glyphs texture atlas descriptor (local for thread safety)
-       VkDescriptorSet         dsSrc;          //source ds
-       VkDescriptorSet         dsGrad;         //gradient uniform buffer
+       VkvgSurface                     pSurf;                  //surface bound to context, set on creation of ctx
+       VkFence                         flushFence;             //context fence
+       VkhImage                        source;                 //source of painting operation
+
+       VkCommandPool           cmdPool;                //local pools ensure thread safety
+       VkCommandBuffer         cmdBuffers[2];  //double cmd buff for context operations
+       VkCommandBuffer         cmd;                    //current recording buffer
+       bool                            cmdStarted;             //prevent flushing empty renderpass
+       bool                            pushCstDirty;   //prevent pushing to gpu if not requested
+       VkDescriptorPool        descriptorPool; //one pool per thread
+       VkDescriptorSet         dsFont;                 //fonts glyphs texture atlas descriptor (local for thread safety)
+       VkDescriptorSet         dsSrc;                  //source ds
+       VkDescriptorSet         dsGrad;                 //gradient uniform buffer
+
+       VkhImage                        fontCacheImg;   //current font cache, may not be the last one, updated only if new glyphs are
+                                                                               //uploaded by the current context
 
        VkRect2D                        bounds;
 
index 6beb912151cbf12e7ba29dd6b7da23769d58317f..a23c2512c74528379c44b22b8338b18871f3970f 100644 (file)
@@ -301,9 +301,9 @@ void vkvg_device_destroy (VkvgDevice dev)
        vkDestroyRenderPass                             (dev->vkDev, dev->renderPass_ClearAll, NULL);
 
        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);
index ca112ad4b6147680864a13eba973f17add904ca2..e5d26c8daa43a38875eb484104bce183c6cac630 100644 (file)
@@ -64,15 +64,6 @@ bool _device_try_get_phyinfo (VkhPhyInfo* phys, uint32_t phyCount, VkPhysicalDev
        }
        return false;
 }
-void _device_flush_all_contexes (VkvgDevice dev){
-       /*VkvgContext ctx = dev->lastCtx;
-       while (ctx != NULL){
-               if (ctx->cmdStarted)
-                       _flush_cmd_until_vx_base (ctx);
-
-               ctx = ctx->pPrev;
-       }*/
-}
 //TODO:save/reload cache in user temp directory
 void _device_create_pipeline_cache(VkvgDevice dev){
 
index 834664e8faaa6195f473c650983106fb4e9d5c2f..6cce240f16cc1b78f94aee677dc1956328c8fbc9 100644 (file)
@@ -135,7 +135,6 @@ VkRenderPass _device_createRenderPassMS     (VkvgDevice dev, VkAttachmentLoadOp load
 VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp);
 void _device_setupPipelines                            (VkvgDevice dev);
 void _device_createDescriptorSetLayout         (VkvgDevice dev);
-void _device_flush_all_contexes                        (VkvgDevice dev);
 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);
index 61fd138915eaa0b795a016bd8ea6cdc51600b2af..17d5958fa5bef4abcb1279d3496562195b8e9a46 100644 (file)
@@ -102,8 +102,6 @@ void _fonts_cache_create (VkvgDevice dev){
 void _increase_font_tex_array (VkvgDevice dev){
        LOG(VKVG_LOG_INFO, "_increase_font_tex_array\n");
 
-       _device_flush_all_contexes (dev);
-
        _font_cache_t* cache = dev->fontCache;
 
        vkWaitForFences         (dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
@@ -150,9 +148,12 @@ void _increase_font_tex_array (VkvgDevice dev){
        void* tmp = memset (&cache->pensY[cache->texLength],0,FONT_CACHE_INIT_LAYERS*sizeof(int));
 
        vkh_image_destroy       (cache->texture);
+
        cache->texLength   = newSize;
        cache->texture     = newImg;
 
+       //_font_cache_update_context_descset(dev, );
+
        /*VkvgContext next = dev->lastCtx;
        while (next != NULL){
                _update_descriptor_set  (next, cache->texture, next->dsFont);
@@ -287,6 +288,19 @@ void _font_cache_destroy (VkvgDevice dev){
 
 }
 
+void _font_cache_update_context_descset (VkvgContext ctx) {
+       if (ctx->fontCacheImg)
+               vkh_image_destroy (ctx->fontCacheImg);
+
+       LOCK_FONTCACHE (ctx->dev)
+
+       ctx->fontCacheImg = ctx->dev->fontCache->texture;
+       vkh_image_reference (ctx->fontCacheImg);
+
+       _update_descriptor_set (ctx, ctx->fontCacheImg, ctx->dsFont);
+
+       UNLOCK_FONTCACHE (ctx->dev)
+}
 //create a new char entry and put glyph in stagging buffer, ready for upload.
 _char_ref* _prepare_char (VkvgDevice dev, VkvgText tr, uint32_t gindex){
        _vkvg_font_t* f = tr->font;
@@ -464,6 +478,8 @@ bool _tryFindFontByName (VkvgContext ctx, _vkvg_font_identity_t** font){
        }
        return false;
 }
+
+#ifdef VKVG_USE_FONTCONFIG
 bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t** resolvedFont) {
 
        LOCK_FONTCACHE(ctx->dev)
@@ -471,7 +487,6 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
        _font_cache_t*  cache = (_font_cache_t*)ctx->dev->fontCache;
        char* fontFile = NULL;
 
-#ifdef VKVG_USE_FONTCONFIG
        FcPattern* pat = FcNameParse((const FcChar8*)ctx->selectedFontName);
        FcConfigSubstitute(cache->config, pat, FcMatchPattern);
        FcDefaultSubstitute(pat);
@@ -479,7 +494,6 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
        FcPattern* font = FcFontMatch(cache->config, pat, &result);
        if (font)
                FcPatternGetString(font, FC_FILE, 0, (FcChar8 **)&fontFile);
-#endif
        *resolvedFont = NULL;
        if (fontFile) {
                //try find font in cache by path
@@ -498,15 +512,14 @@ bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t**
                }
        }
 
-#ifdef VKVG_USE_FONTCONFIG
        FcPatternDestroy(pat);
        FcPatternDestroy(font);
-#endif
 
        UNLOCK_FONTCACHE(ctx->dev)
 
        return (fontFile != NULL);
 }
+#endif
 
 
 //try to find corresponding font in cache (defined by context selectedFont) and create a new font entry if not found.
@@ -516,8 +529,16 @@ void _update_current_font (VkvgContext ctx) {
                if (ctx->selectedFontName[0] == 0)
                        _select_font_face (ctx, "sans");
 
-               if (!_tryFindFontByName(ctx, &ctx->currentFont))
+               if (!_tryFindFontByName (ctx, &ctx->currentFont)) {
+#ifdef VKVG_USE_FONTCONFIG
                        _tryResolveFontNameWithFontConfig (ctx, &ctx->currentFont);
+#else
+                       LOG(VKVG_LOG_ERR, "Unresolved font: %s\n", ctx->selectedFontName);
+                       UNLOCK_FONTCACHE(ctx->dev)
+                       ctx->status = VKVG_STATUS_INVALID_FONT;
+                       return;
+#endif
+               }
 
                ctx->currentFontSize = _find_or_create_font_size (ctx);
                UNLOCK_FONTCACHE(ctx->dev)
@@ -635,6 +656,11 @@ void _font_cache_create_text_run (VkvgContext ctx, const char* text, VkvgText te
        
        UNLOCK_FONTCACHE (ctx->dev)
 
+       if (ctx->fontCacheImg != ctx->dev->fontCache->texture) {
+               vkvg_flush (ctx);
+               _font_cache_update_context_descset (ctx);
+       }
+
        unsigned int string_width_in_pixels = 0;
        for (uint32_t i=0; i < textRun->glyph_count; ++i)
                string_width_in_pixels += textRun->glyphs[i].x_advance >> 6;
@@ -697,14 +723,14 @@ void _font_cache_show_text_run (VkvgContext ctx, VkvgText tr) {
 
        for (uint32_t i=0; i < glyph_count; ++i) {
                _char_ref* cr = tr->font->charLookup[glyph_info[i].codepoint];
-
-               if (cr==NULL)
-                       cr = _prepare_char(tr->dev, tr, glyph_info[i].codepoint);
+               assert((cr!=NULL) && "char lookup failed in _show_text_run.");
+               /*if (cr==NULL)
+                       cr = _prepare_char(tr->dev, tr, glyph_info[i].codepoint);*/
 
                //continue;
-               if (cr!=NULL){
-                       float uvWidth = cr->bounds.width / (float)FONT_PAGE_SIZE;
-                       float uvHeight = cr->bounds.height / (float)FONT_PAGE_SIZE;
+               //if (cr!=NULL){
+                       float uvWidth   = cr->bounds.width  / (float)FONT_PAGE_SIZE;
+                       float uvHeight  = cr->bounds.height / (float)FONT_PAGE_SIZE;
                        vec2 p0 = {pen.x + cr->bmpDiff.x + (tr->glyphs[i].x_offset >> 6),
                                           pen.y - cr->bmpDiff.y + (tr->glyphs[i].y_offset >> 6)};
                        v.pos = p0;
@@ -732,7 +758,7 @@ void _font_cache_show_text_run (VkvgContext ctx, VkvgText tr) {
                        _add_vertex(ctx,v);
 
                        _add_tri_indices_for_rect (ctx, firstIdx);
-               }
+               //}
 
                pen.x += (tr->glyphs[i].x_advance >> 6);
                pen.y -= (tr->glyphs[i].y_advance >> 6);
index d7d656ad4337d88d60af24cac39451b5e50ed675..33cdccd1a7d87f07ef803bfabd3e98d8a2c5da7c 100644 (file)
@@ -201,4 +201,6 @@ void _font_cache_create_text_run            (VkvgContext ctx, const char* text, VkvgText t
 void _font_cache_destroy_text_run              (VkvgText textRun);
 //Draw text run
 void _font_cache_show_text_run                 (VkvgContext ctx, VkvgText tr);
+//update context font cache descriptor set
+void _font_cache_update_context_descset (VkvgContext ctx);
 #endif
index bd14e84f5b12ec102ddc1542b6c693eded34b9af..49818604cdcfb8ec81f056073044d19564120e82 100644 (file)
@@ -1,7 +1,11 @@
+/*
+ * multiple contexts in separate thread on temp surface for each thread
+ * guarded blit on final surface.
+ */
 #include "test.h"
 #include "tinycthread.h"
 
-#define THREAD_COUNT 16
+#define THREAD_COUNT 64
 
 
 static int finishedThreadCount = 0;
index 0485d13d84f76353b5703dce09c2652ce40a6f55..7821581fc9c1c1bd2f75e6e72a9a2225515c2eba 100644 (file)
@@ -1,3 +1,6 @@
+/*
+ * drawing from multiple contexts in separate threads on a single unguarded surface
+ */
 #include "test.h"
 #include "tinycthread.h"
 
@@ -17,23 +20,16 @@ void drawRandomRect (VkvgContext ctx, float s) {
 
        vkvg_rectangle(ctx, x, y, s, s);
 }
-void _before_submit (void* data) {
-       mtx_lock((mtx_t*)data);
-}
-void _after_submit (void* data) {
-       mtx_unlock((mtx_t*)data);
-}
-
 int drawRectsThread () {
        VkvgContext ctx = vkvg_create(surf);
        for (uint32_t i=0; i<test_size; i++) {
                drawRandomRect(ctx, 14.0f);
                vkvg_fill (ctx);
        }
-       vkvg_destroy(ctx);
-       mtx_lock(pmutex);
+       vkvg_destroy (ctx);
+       mtx_lock (pmutex);
        finishedThreadCount++;
-       mtx_unlock(pmutex);
+       mtx_unlock (pmutex);
        return 0;
 }
 void fixedSizeRects(){
@@ -62,6 +58,7 @@ void fixedSizeRects(){
 }
 
 int main(int argc, char *argv[]) {
+       vkvg_log_level = VKVG_LOG_ERR|VKVG_LOG_DEBUG;//|VKVG_LOG_INFO|VKVG_LOG_INFO_PATH|VKVG_LOG_DBG_ARRAYS|VKVG_LOG_FULL;
        PERFORM_TEST (fixedSizeRects, argc, argv);
        return 0;
 }
diff --git a/tests/multithreading/threaded_create_surf.c b/tests/multithreading/threaded_create_surf.c
new file mode 100644 (file)
index 0000000..9789565
--- /dev/null
@@ -0,0 +1,50 @@
+#include "test.h"
+#include "tinycthread.h"
+
+#define THREAD_COUNT 16
+
+
+static int finishedThreadCount = 0;
+static mtx_t* pmutex;
+
+int create_surfs () {
+       for (uint32_t i=0; i<test_size; i++) {
+               VkvgSurface s = vkvg_surface_create(device, test_width, test_height);
+               vkvg_surface_destroy (s);
+       }
+
+       mtx_lock(pmutex);
+       finishedThreadCount++;
+       mtx_unlock(pmutex);
+       return 0;
+}
+
+void fixedSizeRects(){
+       mtx_t mutex;
+       pmutex = &mutex;
+
+       vkvg_device_set_thread_aware (device, 1);
+
+       thrd_t threads[THREAD_COUNT];
+
+       finishedThreadCount = 0;
+       mtx_init (pmutex, mtx_plain);
+       for (uint32_t i=0; i<THREAD_COUNT; i++)
+               thrd_create (&threads[i], create_surfs, NULL);
+
+       const struct timespec ts = {1,0};
+       while (finishedThreadCount < THREAD_COUNT)
+               thrd_sleep(&ts, NULL);
+
+       mtx_lock(pmutex);
+       mtx_unlock(pmutex);
+       mtx_destroy (pmutex);
+       pmutex = NULL;
+
+       vkvg_device_set_thread_aware (device, 0);
+}
+
+int main(int argc, char *argv[]) {
+       PERFORM_TEST (fixedSizeRects, argc, argv);
+       return 0;
+}
diff --git a/vkh b/vkh
index e448f9f0e10fbc1d0a62ce471c73880d207e7d66..8da9a46d33150c8216b8ee868269890a041e7c46 160000 (submodule)
--- a/vkh
+++ b/vkh
@@ -1 +1 @@
-Subproject commit e448f9f0e10fbc1d0a62ce471c73880d207e7d66
+Subproject commit 8da9a46d33150c8216b8ee868269890a041e7c46