_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;
_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);
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];
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,
free(ctx->vertexCache);
free(ctx->indexCache);
+ vkh_image_destroy (ctx->fontCacheImg);
//TODO:check this for source counter
//vkh_image_destroy (ctx->source);
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;
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);
}
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){
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);
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);
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);
}
+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;
}
return false;
}
+
+#ifdef VKVG_USE_FONTCONFIG
bool _tryResolveFontNameWithFontConfig (VkvgContext ctx, _vkvg_font_identity_t** resolvedFont) {
LOCK_FONTCACHE(ctx->dev)
_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);
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
}
}
-#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.
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)
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;
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;
_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);
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
+/*
+ * 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;
+/*
+ * drawing from multiple contexts in separate threads on a single unguarded surface
+ */
#include "test.h"
#include "tinycthread.h"
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(){
}
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;
}
--- /dev/null
+#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;
+}
-Subproject commit e448f9f0e10fbc1d0a62ce471c73880d207e7d66
+Subproject commit 8da9a46d33150c8216b8ee868269890a041e7c46