From 4299868a13a872f70a3b120665d53fe2fe21f1ab Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jean-Philippe=20Bruy=C3=A8re?= Date: Wed, 1 May 2019 17:57:01 +0200 Subject: [PATCH] clear new surface with first renderpass --- include/vkvg.h | 2 +- src/cross_os.c | 47 +++++++++++++++++++++++ src/cross_os.h | 37 +++++++++++++++++++ src/vkvg_context.c | 23 +++++++++--- src/vkvg_context_internal.c | 2 +- src/vkvg_device.c | 7 +++- src/vkvg_device_internal.c | 6 +-- src/vkvg_device_internal.h | 3 +- src/vkvg_surface.c | 1 + src/vkvg_surface_internal.h | 1 + template.c | 14 +++++++ tests/common/test.c | 61 +++++++++++++++++++++++++++++- tests/common/test.h | 6 +++ tests/painting.c | 74 +++++++++++++++++++++++++++++-------- 14 files changed, 253 insertions(+), 31 deletions(-) create mode 100644 src/cross_os.c create mode 100644 src/cross_os.h create mode 100644 template.c diff --git a/include/vkvg.h b/include/vkvg.h index 618fe7f..ec30504 100644 --- a/include/vkvg.h +++ b/include/vkvg.h @@ -43,7 +43,7 @@ extern "C" { #define LOG_FULL 0xff #ifdef DEBUG -static uint8_t log_level = LOG_ERR;// LOG_INFO | LOG_DEBUG; +static uint8_t log_level = LOG_ERR;// | LOG_INFO | LOG_DEBUG; #define LOG(level,...) (log_level & level) ? fprintf (stdout, __VA_ARGS__):true; #else #define LOG diff --git a/src/cross_os.c b/src/cross_os.c new file mode 100644 index 0000000..ba53b6a --- /dev/null +++ b/src/cross_os.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Jean-Philippe Bruyère + * + * 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 "cross_os.h" +#include +#include +#include + + +int directoryExists (const char* path) { +#ifdef _WIN32 + return getenv("HOME"); +#elif __APPLE__ +#elif __unix__ + struct stat st = {0}; + return stat(path, &st)+1; +#endif + return -1; +} +const char* getUserDir () { +#ifdef _WIN32 + return getenv("HOME"); +#elif __APPLE__ +#elif __unix__ + struct passwd *pw = getpwuid(getuid()); + return pw->pw_dir; +#endif + return -1; +} diff --git a/src/cross_os.h b/src/cross_os.h new file mode 100644 index 0000000..f9932b1 --- /dev/null +++ b/src/cross_os.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018 Jean-Philippe Bruyère + * + * 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 CROSS_OS_H +#define CROSS_OS_H + +//cross platform os helpers +#ifdef _WIN32 +#include "windows.h" +#elif __APPLE__ +#elif __unix__ +#include +#include +#include +#endif + +const char* getUserDir (); + +#endif // CROSS_OS_H diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 2a5db0c..894ea50 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -32,9 +32,9 @@ static uint32_t dlpCount = 0; #endif static VkClearValue clearValues[3] = { - { {{0.0f, 0.0f, 0.0f, 1.0f}} }, - { {{1.0f, 0}} }, - { {{0.0f, 0.0f, 0.0f, 1.0f}} } + { 0.0f, 0.0f, 0.0f, 0.0f }, + { 1.0f, 0 }, + { 0.0f, 0.0f, 0.0f, 0.0f } }; /** @@ -44,11 +44,11 @@ static VkClearValue clearValues[3] = { */ VkvgContext vkvg_create(VkvgSurface surf) { - LOG(LOG_INFO, "CREATE Context: surf = %lu\n", (ulong)surf); - VkvgDevice dev = surf->dev; VkvgContext ctx = (vkvg_context*)calloc(1, sizeof(vkvg_context)); + LOG(LOG_INFO, "CREATE Context: ctx = %lu; surf = %lu\n", (ulong)ctx, (ulong)surf); + if (ctx==NULL) { dev->status = VKVG_STATUS_NO_MEMORY; return NULL; @@ -80,7 +80,14 @@ VkvgContext vkvg_create(VkvgSurface surf) ctx->renderPassBeginInfo.renderArea.extent.width = ctx->pSurf->width; ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height; ctx->renderPassBeginInfo.pClearValues = clearValues; - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass_ClearStencil; + + if (ctx->pSurf->new) + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass_ClearAll; + else + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass_ClearStencil; + + ctx->pSurf->new = false; + ctx->renderPassBeginInfo.clearValueCount = 3; ctx->pPrev = surf->dev->lastCtx; @@ -160,6 +167,8 @@ void vkvg_destroy (VkvgContext ctx) _flush_cmd_buff(ctx); + LOG(LOG_INFO, "DESTROY Context: ctx = %lu; surf = %lu\n", (ulong)ctx, (ulong)ctx->pSurf); + if (ctx->pattern) vkvg_pattern_destroy (ctx->pattern); @@ -456,6 +465,8 @@ void vkvg_clip_preserve (VkvgContext ctx){ return; _finish_path(ctx); + LOG(LOG_INFO, "CLIP: ctx = %lu; path cpt = %d;\n", ctx, ctx->pathPtr / 2); + if (ctx->pointCount * 4 > ctx->sizeIndices - ctx->indCount)//flush if vk buff is full vkvg_flush(ctx); diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 58eaac5..2a76b0e 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -235,7 +235,7 @@ inline void _submit_wait_and_reset_cmd (VkvgContext ctx){ }*/ void _end_render_pass (VkvgContext ctx) { - LOG(LOG_INFO, "FLUSH Context: ctx = %lu; vert cpt = %d; ind cpt = %d\n", ctx, ctx->vertCount -4, ctx->indCount - 6); + LOG(LOG_INFO, "END RENDER PASS: ctx = %lu; vert cpt = %d; ind cpt = %d\n", ctx, ctx->vertCount -4, ctx->indCount - 6); _record_draw_cmd (ctx); CmdEndRenderPass (ctx->cmd); ctx->renderPassBeginInfo.renderPass = ctx->pSurf->dev->renderPass; diff --git a/src/vkvg_device.c b/src/vkvg_device.c index e7e9f32..53af110 100644 --- a/src/vkvg_device.c +++ b/src/vkvg_device.c @@ -89,11 +89,13 @@ VkvgDevice vkvg_device_create_multisample(VkInstance inst, VkPhysicalDevice phy, _create_pipeline_cache (dev); _init_fonts_cache (dev); if (dev->deferredResolve || dev->samples == VK_SAMPLE_COUNT_1_BIT){ - dev->renderPass = _setupRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD); - dev->renderPass_ClearStencil = _setupRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR); + dev->renderPass = _createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD); + dev->renderPass_ClearStencil = _createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR); + dev->renderPass_ClearAll = _createRenderPassNoResolve (dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR); }else{ dev->renderPass = _createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_LOAD); dev->renderPass_ClearStencil = _createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_LOAD_OP_CLEAR); + dev->renderPass_ClearAll = _createRenderPassMS (dev, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR); } _createDescriptorSetLayout (dev); _setupPipelines (dev); @@ -135,6 +137,7 @@ void vkvg_device_destroy (VkvgDevice dev) vkDestroyPipelineCache (dev->vkDev, dev->pipelineCache, NULL); vkDestroyRenderPass (dev->vkDev, dev->renderPass, NULL); vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearStencil, NULL); + vkDestroyRenderPass (dev->vkDev, dev->renderPass_ClearAll, NULL); vkWaitForFences (dev->vkDev, 1, &dev->fence, VK_TRUE, UINT64_MAX); diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c index d8ab85d..9e92efb 100644 --- a/src/vkvg_device_internal.c +++ b/src/vkvg_device_internal.c @@ -47,7 +47,7 @@ void _create_pipeline_cache(VkvgDevice dev){ VK_CHECK_RESULT(vkCreatePipelineCache(dev->vkDev, &pipelineCacheCreateInfo, NULL, &dev->pipelineCache)); } -VkRenderPass _setupRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) +VkRenderPass _createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) { VkAttachmentDescription attColor = { .format = FB_COLOR_FORMAT, @@ -115,8 +115,8 @@ VkRenderPass _createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAt VkAttachmentDescription attColorResolve = { .format = FB_COLOR_FORMAT, .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, + .loadOp = loadOp, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h index 8bcca38..e26dcf5 100644 --- a/src/vkvg_device_internal.h +++ b/src/vkvg_device_internal.h @@ -61,6 +61,7 @@ typedef struct _vkvg_device_t{ MUTEX gQMutex; /**< queue submission has to be externally syncronized */ VkRenderPass renderPass; /**< Vulkan render pass, common for all surfaces */ VkRenderPass renderPass_ClearStencil;/**< Vulkan render pass for first draw with context, stencil has to be cleared */ + VkRenderPass renderPass_ClearAll; /**< Vulkan render pass for new surface, clear all attacments*/ uint32_t references; /**< Reference count, prevent destroying device if still in use */ VkCommandPool cmdPool; /**< Global command pool for processing on surfaces without context */ @@ -102,7 +103,7 @@ void _create_empty_texture (VkvgDevice dev); void _check_image_format_properties (VkvgDevice dev); void _create_pipeline_cache (VkvgDevice dev); VkRenderPass _createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp); -VkRenderPass _setupRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp); +VkRenderPass _createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp); void _setupPipelines (VkvgDevice dev); void _createDescriptorSetLayout (VkvgDevice dev); void _flush_all_contexes (VkvgDevice dev); diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c index f3958e0..df9ac8d 100644 --- a/src/vkvg_surface.c +++ b/src/vkvg_surface.c @@ -170,6 +170,7 @@ VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height) surf->dev = dev; surf->width = width; surf->height = height; + surf->new = true;//used to clear all attacments on first render pass _init_surface (surf); diff --git a/src/vkvg_surface_internal.h b/src/vkvg_surface_internal.h index 11e4408..983b285 100644 --- a/src/vkvg_surface_internal.h +++ b/src/vkvg_surface_internal.h @@ -36,6 +36,7 @@ typedef struct _vkvg_surface_t { VkhImage imgMS; VkhImage stencil; uint32_t references; + bool new; }vkvg_surface; void _clear_surface (VkvgSurface surf, VkImageAspectFlags aspect); diff --git a/template.c b/template.c new file mode 100644 index 0000000..3cb99af --- /dev/null +++ b/template.c @@ -0,0 +1,14 @@ +#include "test.h" + +void test(){ + VkvgContext ctx = vkvg_create(surf); + + vkvg_destroy(ctx); +} + +int main(int argc, char *argv[]) { + + perform_test (test, 600, 800); + + return 0; +} diff --git a/tests/common/test.c b/tests/common/test.c index 285b253..edd7ac9 100644 --- a/tests/common/test.c +++ b/tests/common/test.c @@ -63,11 +63,70 @@ 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); + VkhPresenter r = e->renderer; + vkengine_set_key_callback (e, key_callback); + vkengine_set_mouse_but_callback(e, mouse_button_callback); + vkengine_set_cursor_pos_callback(e, mouse_move_callback); + vkengine_set_scroll_callback(e, scroll_callback); + + bool deferredResolve = false; + + 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); + + vkvg_device_set_dpy(device, 96, 96); + + surf = vkvg_surface_create(device, width, height); + + vkh_presenter_build_blit_cmd (r, vkvg_surface_get_vk_image(surf), width, height); +} +void run_test_func (void(*testfunc)(void),uint width, uint height) { + bool deferredResolve = false; + VkhPresenter r = e->renderer; + + struct timeval before , after; + double frameTime = 0, frameTimeAccum = 0, frameCount = 0; + + while (!vkengine_should_close (e)) { + glfwPollEvents(); + + gettimeofday(&before , NULL); + + 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); + + vkDeviceWaitIdle(e->dev->dev); + + gettimeofday(&after , NULL); + + frameTimeAccum += time_diff(before , after); + frameCount++; + } + + frameTime = frameTimeAccum / frameCount; + printf ("frame (µs): %.0lf\nfps: %lf\n", frameTime, floor(1000000 / frameTime)); + +} +void clear_test () { + vkDeviceWaitIdle(e->dev->dev); + + vkvg_surface_destroy (surf); + vkvg_device_destroy (device); + + vkengine_destroy (e); +} void perform_test (void(*testfunc)(void),uint width, uint height) { //dumpLayerExts(); - vk_engine_t* e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_MAILBOX_KHR, width, height); + e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, VK_PRESENT_MODE_MAILBOX_KHR, width, height); VkhPresenter r = e->renderer; vkengine_set_key_callback (e, key_callback); vkengine_set_mouse_but_callback(e, mouse_button_callback); diff --git a/tests/common/test.h b/tests/common/test.h index dc83464..4841767 100644 --- a/tests/common/test.h +++ b/tests/common/test.h @@ -73,5 +73,11 @@ extern bool mouseDown; extern VkvgDevice device; extern VkvgSurface surf; +//run test in one step void perform_test (void(*testfunc)(void),uint width, uint height); void randomize_color (VkvgContext ctx); + +//run test in 3 step: init, run, clear. +void init_test (uint width, uint height); +void run_test_func (void(*testfunc)(void),uint width, uint height); +void clear_test (); diff --git a/tests/painting.c b/tests/painting.c index 39eb09d..f8ac370 100644 --- a/tests/painting.c +++ b/tests/painting.c @@ -1,38 +1,80 @@ #include "test.h" +static VkvgSurface surf2; + void test(){ - VkvgSurface surf2 = vkvg_surface_create (device,400,400);; - VkvgContext ctx = vkvg_create (surf2); + VkvgContext ctx = vkvg_create (surf); - vkvg_set_source_rgba(ctx,1.0,0.,0.,1.0); + vkvg_set_source_surface(ctx,surf2,0,0); vkvg_paint (ctx); - vkvg_destroy (ctx); - ctx = vkvg_create (surf); - vkvg_set_source_rgba(ctx,0.1,0.1,0.3,1.0); - vkvg_paint (ctx); + return; + + //vkvg_set_source_rgba(ctx,0.1,0.1,0.3,1.0); + //vkvg_paint (ctx); - //vkvg_set_source_surface(ctx,surf2,0,0); + for (int i=0; i<10; i++) { + vkvg_translate(ctx,50,50); + + /*vkvg_save(ctx); + + vkvg_rectangle(ctx,0,0,200,200); + vkvg_clip_preserve(ctx); + vkvg_set_operator(ctx,VKVG_OPERATOR_CLEAR); + vkvg_fill(ctx); + vkvg_set_operator(ctx,VKVG_OPERATOR_OVER);*/ + + vkvg_set_source_rgba(ctx,0.0,0.0,0.0,0.3f); + vkvg_move_to(ctx,0,0); + vkvg_line_to(ctx,0,200); + vkvg_set_line_width(ctx,10); + vkvg_stroke(ctx); + vkvg_set_source_surface(ctx,surf2,0,0); + vkvg_paint (ctx); + + //vkvg_restore(ctx); + } //VkvgPattern pat = vkvg_get_source (ctx); - VkvgPattern pat = vkvg_pattern_create_for_surface(surf2); + /*VkvgPattern pat = vkvg_pattern_create_for_surface(surf2); vkvg_pattern_set_extend (pat,VKVG_EXTEND_REFLECT); - vkvg_set_source(ctx,pat); - //vkvg_paint (ctx); + vkvg_set_source(ctx,pat);*/ //vkvg_set_source_rgba(ctx,0,1,0,1.0); - vkvg_rectangle(ctx,100,100,200,200); - vkvg_fill(ctx); + //vkvg_rectangle(ctx,100,100,200,200); + //vkvg_fill(ctx); vkvg_destroy (ctx); - vkvg_surface_destroy (surf2); - vkvg_pattern_destroy (pat); + + //vkvg_pattern_destroy (pat); } int main(int argc, char *argv[]) { - perform_test (test, 1024, 768); + init_test(1024, 768); + + surf2 = vkvg_surface_create (device,400,400); + + VkvgContext ctx = vkvg_create (surf2); + + vkvg_set_source_rgba(ctx,1.0,0.,0.,0.2f); + vkvg_paint (ctx); + vkvg_set_source_rgba(ctx,1.0,1.0,0.,0.5f); + vkvg_move_to(ctx,10,10); + vkvg_line_to(ctx,200,200); + vkvg_set_line_width(ctx,10); + vkvg_stroke(ctx); + vkvg_set_source_rgba(ctx,1.0,1.0,1.0,0.6f); + vkvg_rectangle(ctx,0,0,400,400); + vkvg_stroke(ctx); + + vkvg_destroy (ctx); + + run_test_func(test, 1024, 768); + + vkvg_surface_destroy (surf2); + clear_test(); return 0; } -- 2.47.3