From 28961d3f5638d8a268a78a0a3562c75f615d166c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Mon, 2 Sep 2019 22:27:25 +0200 Subject: [PATCH] direct draw on swapchain image as option, several tests --- CMakeLists.txt | 5 ++- README.md | 6 +-- src/vkvg_context.c | 13 ++++--- src/vkvg_context_internal.c | 31 +++++++++++---- src/vkvg_context_internal.h | 8 ++-- src/vkvg_surface.c | 4 +- tests/common/test.c | 78 ++++++++++++++++++++++++++++++++----- tests/common/test.h | 6 +++ tests/hlines.c | 10 ++--- tests/lines.c | 20 ++++++---- tests/multilines.c | 16 +++++--- tests/random_cirles.c | 37 ++++++++++++++++++ tests/random_rects.c | 25 ++++++------ tests/rect_fill.c | 18 +++------ tests/vlines.c | 8 ++-- 15 files changed, 206 insertions(+), 79 deletions(-) create mode 100644 tests/random_cirles.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c2b7f46..d569c11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,10 @@ ELSE() UNSET(ENABLE_VALIDATION CACHE) UNSET(ENABLE_WIRED_FILL CACHE) ENDIF() - +OPTION(VKVG_TEST_DIRECT_DRAW "Draw directly on backend surface, if off surface is blitted." ON) +IF (VKVG_TEST_DIRECT_DRAW) + ADD_DEFINITIONS (-DVKVG_TEST_DIRECT_DRAW) +ENDIF () OPTION(VKVG_PREMULT_ALPHA "use premultiplied alpha for internal rendering" ON) IF (VKVG_PREMULT_ALPHA) ADD_DEFINITIONS (-DVKVG_PREMULT_ALPHA) diff --git a/README.md b/README.md index 89c6dc2..3fc979b 100644 --- a/README.md +++ b/README.md @@ -74,13 +74,13 @@ make # Run Make ### To Do -- [ ] Use Scissor where possible. -- [ ] Improve stroke algorithms. +- [x] Use Scissor where possible. +- [x] Improve stroke algorithms. - [ ] Radial gradients. - [ ] Dashed lines. - [ ] Operators. - [x] Optimize vulkan memory allocations by sub-allocating from a single shared memory chunk per type. -- [ ] Optimize command submissions. +- [x] Optimize command submissions. - [x] Test SDF font rendering. - [x] Avoid line joins inside curves and arc. - [ ] Structured unit testing. diff --git a/src/vkvg_context.c b/src/vkvg_context.c index e877bd4..2643afc 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -99,9 +99,12 @@ VkvgContext vkvg_create(VkvgSurface surf) ctx->pSurf->new = false; - ctx->renderPassBeginInfo.clearValueCount = 3; + if (dev->samples == VK_SAMPLE_COUNT_1_BIT) + ctx->renderPassBeginInfo.clearValueCount = 2; + else + ctx->renderPassBeginInfo.clearValueCount = 3; - ctx->pPrev = surf->dev->lastCtx; + ctx->pPrev = surf->dev->lastCtx; if (ctx->pPrev != NULL) ctx->pPrev->pNext = ctx; surf->dev->lastCtx = ctx; @@ -140,7 +143,7 @@ VkvgContext vkvg_create(VkvgSurface surf) */ void vkvg_flush (VkvgContext ctx){ _flush_cmd_buff(ctx); - _wait_flush_fence(ctx); + //_wait_flush_fence(ctx); /* #ifdef DEBUG @@ -686,8 +689,8 @@ void vkvg_stroke_preserve (VkvgContext ctx) iR = ctx->pathes[ptrPath]&PATH_ELT_MASK; _build_vb_step(ctx,v,hw,iL,i,iR, false); - uint32_t* inds = &ctx->indexCache [ctx->indCount-6]; - uint32_t ii = firstIdx; + VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount-6]; + VKVG_IBO_INDEX_TYPE ii = firstIdx; inds[1] = ii; inds[4] = ii; inds[5] = ii+1; diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index cdf025c..504fcaa 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -42,11 +42,23 @@ void _check_cmd_buff_state (VkvgContext ctx) { else if (ctx->pushCstDirty) _update_push_constants(ctx); } +void _check_vbo_size (VkvgContext ctx) { + if (ctx->sizeVertices - ctx->vertCount > VKVG_ARRAY_THRESHOLD) + return; + ctx->sizeVertices += VKVG_VBO_SIZE; + ctx->vertexCache = (Vertex*) realloc (ctx->vertexCache, ctx->sizeVertices * sizeof(Vertex)); +} +void _check_ibo_size (VkvgContext ctx) { + if (ctx->sizeIndices - ctx->indCount > VKVG_ARRAY_THRESHOLD) + return; + ctx->sizeIndices += VKVG_IBO_SIZE; + ctx->indexCache = (VKVG_IBO_INDEX_TYPE*) realloc (ctx->vertexCache, ctx->sizeVertices * sizeof(VKVG_IBO_INDEX_TYPE)); +} void _check_pathes_array (VkvgContext ctx){ if (ctx->sizePathes - ctx->pathPtr - ctx->curvePtr > VKVG_ARRAY_THRESHOLD) return; ctx->sizePathes += VKVG_PATHES_SIZE; - ctx->pathes = (uint32_t*) realloc (ctx->pathes, ctx->sizePathes*sizeof(uint32_t)); + ctx->pathes = (uint32_t*) realloc (ctx->pathes, ctx->sizePathes * sizeof(uint32_t)); } //when empty, ptr is even, else it's odd //when empty, no current point is defined. @@ -142,7 +154,7 @@ void _create_gradient_buff (VkvgContext ctx){ void _create_vertices_buff (VkvgContext ctx){ ctx->vertexCache = (Vertex*)malloc(ctx->sizeVertices * sizeof(Vertex)); - ctx->indexCache = (uint32_t*)malloc(ctx->sizeVertices * sizeof(uint32_t)); + ctx->indexCache = (VKVG_IBO_INDEX_TYPE*)malloc(ctx->sizeVertices * sizeof(VKVG_IBO_INDEX_TYPE)); vkvg_buffer_create (ctx->pSurf->dev, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, @@ -151,7 +163,7 @@ void _create_vertices_buff (VkvgContext ctx){ vkvg_buffer_create (ctx->pSurf->dev, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_CPU_TO_GPU, - ctx->sizeIndices * sizeof(uint32_t), &ctx->indices); + ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices); } const vec3 blankuv = {}; void _add_vertexf (VkvgContext ctx, float x, float y){ @@ -169,7 +181,7 @@ void _set_vertex(VkvgContext ctx, uint32_t idx, Vertex v){ ctx->vertexCache[idx] = v; } void _add_tri_indices_for_rect (VkvgContext ctx, uint32_t i){ - uint32_t* inds = &ctx->indexCache[ctx->indCount]; + VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount]; inds[0] = i; inds[1] = i+2; inds[2] = i+1; @@ -179,7 +191,7 @@ void _add_tri_indices_for_rect (VkvgContext ctx, uint32_t i){ ctx->indCount+=6; } void _add_triangle_indices(VkvgContext ctx, uint32_t i0, uint32_t i1, uint32_t i2){ - uint32_t* inds = &ctx->indexCache[ctx->indCount]; + VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache[ctx->indCount]; inds[0] = i0; inds[1] = i1; inds[2] = i2; @@ -279,7 +291,7 @@ void _flush_cmd_buff (VkvgContext ctx){ return; memcpy(ctx->vertices.allocInfo.pMappedData, ctx->vertexCache, ctx->vertCount * sizeof (Vertex)); - memcpy(ctx->indices.allocInfo.pMappedData, ctx->indexCache, ctx->indCount * sizeof (uint32_t)); + memcpy(ctx->indices.allocInfo.pMappedData, ctx->indexCache, ctx->indCount * sizeof (VKVG_IBO_INDEX_TYPE)); _end_render_pass (ctx); vkh_cmd_end (ctx->cmd); @@ -336,7 +348,10 @@ void _start_cmd_for_render_pass (VkvgContext ctx) { VkDeviceSize offsets[1] = { 0 }; CmdBindVertexBuffers(ctx->cmd, 0, 1, &ctx->vertices.buffer, offsets); - CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT32); + if (sizeof (VKVG_IBO_INDEX_TYPE) == 4) + CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT32); + else + CmdBindIndexBuffer(ctx->cmd, ctx->indices.buffer, 0, VK_INDEX_TYPE_UINT16); _update_push_constants (ctx); @@ -540,7 +555,7 @@ void add_line(vkvg_context* ctx, vec2 p1, vec2 p2, vec4 col){ _add_vertex(ctx, v); v.pos = p2; _add_vertex(ctx, v); - uint32_t* inds = &ctx->indexCache [ctx->indCount]; + VKVG_IBO_INDEX_TYPE* inds = &ctx->indexCache [ctx->indCount]; inds[0] = ctx->vertCount - 2; inds[1] = ctx->vertCount - 1; ctx->indCount+=2; diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index 720ccfc..400c87d 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -33,6 +33,7 @@ #define VKVG_IBO_SIZE VKVG_VBO_SIZE * 6 #define VKVG_PATHES_SIZE 16 #define VKVG_ARRAY_THRESHOLD 4 +#define VKVG_IBO_INDEX_TYPE uint16_t typedef struct{ vec2 pos; @@ -105,9 +106,8 @@ typedef struct _vkvg_context_t { size_t sizeVertices; //reserved size uint32_t vertCount; //effective vertices count - Vertex* vertexCache; - uint32_t* indexCache; - + Vertex* vertexCache; + VKVG_IBO_INDEX_TYPE* indexCache; //pathes, exists until stroke of fill vec2* points; //points array @@ -159,6 +159,8 @@ typedef struct _ear_clip_point{ bool _current_path_is_empty (VkvgContext ctx); void _start_sub_path (VkvgContext ctx, float x, float y); +void _check_vbo_size (VkvgContext ctx); +void _check_ibo_size (VkvgContext ctx); void _check_pathes_array (VkvgContext ctx); void _finish_path (VkvgContext ctx); void _clear_path (VkvgContext ctx); diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c index a401890..e280353 100644 --- a/src/vkvg_surface.c +++ b/src/vkvg_surface.c @@ -381,7 +381,9 @@ void vkvg_surface_destroy(VkvgSurface surf) return; vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL); - vkh_image_destroy(surf->img); + if (!surf->img->imported) + vkh_image_destroy(surf->img); + vkh_image_destroy(surf->imgMS); vkh_image_destroy(surf->stencil); diff --git a/tests/common/test.c b/tests/common/test.c index 17e5ff8..869b95e 100644 --- a/tests/common/test.c +++ b/tests/common/test.c @@ -1,4 +1,4 @@ -#include "test.h" +#include "test.h" float panX = 0.f; float panY = 0.f; @@ -10,6 +10,11 @@ bool mouseDown = false; VkvgDevice device = NULL; VkvgSurface surf = NULL; +uint iterations = 250; // items drawn in one run, or complexity +uint runs = 10; // repeat test n times + +static vk_engine_t* e; + static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (action != GLFW_PRESS) return; @@ -63,7 +68,6 @@ void randomize_color (VkvgContext ctx) { (float)rand()/RAND_MAX ); } -static vk_engine_t* e; void init_test (uint width, uint height){ e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_MAILBOX_KHR, width, height); @@ -73,9 +77,9 @@ void init_test (uint width, uint height){ vkengine_set_cursor_pos_callback(e, mouse_move_callback); vkengine_set_scroll_callback(e, scroll_callback); - bool deferredResolve = false; + bool deferredResolve = true; - device = vkvg_device_create_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, VK_SAMPLE_COUNT_1_BIT, deferredResolve); + device = vkvg_device_create_multisample(vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0, VK_SAMPLE_COUNT_4_BIT, deferredResolve); vkvg_device_set_dpy(device, 96, 96); @@ -123,6 +127,10 @@ void clear_test () { vkengine_destroy (e); } +#ifdef VKVG_TEST_DIRECT_DRAW +VkvgSurface* surfaces; +#endif + void perform_test (void(*testfunc)(void),uint width, uint height) { //dumpLayerExts(); @@ -139,12 +147,15 @@ void perform_test (void(*testfunc)(void),uint width, uint height) { vkvg_device_set_dpy(device, 96, 96); +#ifdef VKVG_TEST_DIRECT_DRAW + VkFence* fences = (VkFence*)calloc(r->imgCount, sizeof (VkFence)); + surfaces = (VkvgSurface*)malloc(r->imgCount * sizeof (VkvgSurface)); + for (uint i=0; i < r->imgCount;i++) + surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]); +#else surf = vkvg_surface_create(device, width, height); - - //vkvg_surface_clear(surf); - vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height); - +#endif struct timeval before , after; double frameTime = 0, frameTimeAccum = 0, frameCount = 0; @@ -153,20 +164,56 @@ void perform_test (void(*testfunc)(void),uint width, uint height) { gettimeofday(&before , NULL); +#ifdef VKVG_TEST_DIRECT_DRAW + VkFence fence = vkh_fence_create (e->dev); + + if (!vkh_presenter_acquireNextImage(r, fence)) { + for (uint i=0; i < r->imgCount;i++){ + if (fences[i]!=NULL){ + vkDestroyFence (e->dev->dev, fences[i], NULL); + fences[i] = NULL; + } + vkvg_surface_destroy(surfaces[i]); + surfaces[i] = vkvg_surface_create_for_VkhImage (device, r->ScBuffers[i]); + } + vkDestroyFence (e->dev->dev, fence, NULL); + }else{ + surf = surfaces[r->currentScBufferIndex]; + if (fences[r->currentScBufferIndex] != NULL){ + vkWaitForFences (e->dev->dev, 1, &fences[r->currentScBufferIndex], VK_TRUE, UINT64_MAX); + vkDestroyFence (e->dev->dev, fences[r->currentScBufferIndex], NULL); + } + fences[r->currentScBufferIndex] = fence; + + testfunc(); + + if (deferredResolve) + vkvg_multisample_surface_resolve(surf); + + VkPresentInfoKHR present = { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + .swapchainCount = 1, + .pSwapchains = &r->swapChain, + .pImageIndices = &r->currentScBufferIndex }; + + /* Make sure command buffer is finished before presenting */ + VK_CHECK_RESULT(vkQueuePresentKHR(r->queue, &present)); + } +#else testfunc(); if (deferredResolve) vkvg_multisample_surface_resolve(surf); if (!vkh_presenter_draw (r)) vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height); +#endif - vkDeviceWaitIdle(e->dev->dev); + //vkDeviceWaitIdle(e->dev->dev); gettimeofday(&after , NULL); frameTimeAccum += time_diff(before , after); frameCount++; - fflush(stdout); + //fflush(stdout); } frameTime = frameTimeAccum / frameCount; @@ -174,7 +221,18 @@ void perform_test (void(*testfunc)(void),uint width, uint height) { vkDeviceWaitIdle(e->dev->dev); +#ifdef VKVG_TEST_DIRECT_DRAW + for (int i=0; iimgCount;i++){ + vkvg_surface_destroy (surfaces[i]); + if (fences[i]!=NULL) + vkDestroyFence (e->dev->dev, fences[i], NULL); + } + free (fences); + free (surfaces); +#else vkvg_surface_destroy (surf); +#endif + vkvg_device_destroy (device); vkengine_destroy (e); diff --git a/tests/common/test.h b/tests/common/test.h index 4841767..8d15d05 100644 --- a/tests/common/test.h +++ b/tests/common/test.h @@ -7,6 +7,9 @@ #include "vkh_device.h" #include "vkh_presenter.h" +#define M_PIF 3.14159265359f /* float pi */ +#define M_PIF_MULT_2 6.28318530718f + #ifdef _WIN32 // MSC_VER #define WIN32_LEAN_AND_MEAN #define NOMINMAX @@ -63,6 +66,9 @@ #include #endif // _WIN32 +extern uint iterations; +extern uint runs; + extern float panX; extern float panY; extern float lastX; diff --git a/tests/hlines.c b/tests/hlines.c index 3246793..d5a40a2 100644 --- a/tests/hlines.c +++ b/tests/hlines.c @@ -11,14 +11,14 @@ void test(){ VkvgContext ctx = vkvg_create(surf); //vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_EVEN_ODD); - vkvg_set_line_width(ctx,20); + vkvg_set_line_width(ctx,1); //vkvg_set_line_join(ctx,VKVG_LINE_JOIN_BEVEL); - for (int i=0; i<250; i++) { + for (uint i=0; i