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);
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");
#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);
}
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;
}
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!!
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];
#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"
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
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};
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){
#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");
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);
*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
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) {
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) {
#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
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 */
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;
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
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;
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));
_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,
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));
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
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);
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;
#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.
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*/
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);
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;
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);
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;
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)
}
vkh_cmd_end (cmd);
- _submit_cmd (dev, &cmd, dev->fence);
+ _submit_cmd (dev, &cmd, &dev->syncCtx);
}
void _create_surface_main_image (VkvgSurface surf){
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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
#include "test.h"
#include "tinycthread.h"
-#define THREAD_COUNT 2
+#define THREAD_COUNT 8
static int finishedThreadCount = 0;
}
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++) {
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++) {
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[]) {
-Subproject commit e448f9f0e10fbc1d0a62ce471c73880d207e7d66
+Subproject commit 4439697af748a6101294cd30d2e7facc4eeaf568