diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-23 19:47:41 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-23 19:47:41 +0200 |
| commit | 64bdd9f5b5a9d515de420830de085ff5203b9278 (patch) | |
| tree | 3a475994e51f141eb0c36a5982fd7d727f3fd7c5 | |
| parent | 15fd8e20f23c3fea2c41fa5def986454631c9d9c (diff) | |
new save restore wip
| -rw-r--r-- | samples/tests/save_restore.cpp | 66 | ||||
| -rw-r--r-- | src/vkvg_context.c | 151 | ||||
| -rw-r--r-- | src/vkvg_context_internal.c | 4 | ||||
| -rw-r--r-- | src/vkvg_context_internal.h | 4 | ||||
| -rw-r--r-- | src/vkvg_device_internal.h | 6 | ||||
| -rw-r--r-- | src/vkvg_surface_internal.c | 23 |
6 files changed, 115 insertions, 139 deletions
diff --git a/samples/tests/save_restore.cpp b/samples/tests/save_restore.cpp index 7bbcb41..66168cb 100644 --- a/samples/tests/save_restore.cpp +++ b/samples/tests/save_restore.cpp @@ -75,6 +75,72 @@ TEST(save_restrore_clipped20) { vkvg_surface_destroy(imgSurf); vkvg_destroy(ctx); } +TEST(save_restrore_nz) { + VkvgContext ctx = vkvg_create(test->surf); + vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO); + + vkvg_rectangle(ctx, 50, 50, 200, 200); + vkvg_clip(ctx); + + vkvg_set_source_rgb(ctx, 0, 0, 1); + vkvg_paint(ctx); + + vkvg_rectangle(ctx, 0, 0, 220, 220); + vkvg_set_source_rgb(ctx, 1, 0, 0); + vkvg_fill(ctx); + + vkvg_destroy(ctx); +} +TEST(save_restrore_nz2) { + VkvgContext ctx = vkvg_create(test->surf); + vkvg_set_fill_rule(ctx, VKVG_FILL_RULE_NON_ZERO); + + vkvg_rectangle(ctx, 50, 50, 200, 200); + vkvg_clip(ctx); + + vkvg_set_source_rgb(ctx, 0, 0, 1); + vkvg_paint(ctx); + + vkvg_save(ctx); + + vkvg_rectangle(ctx, 75, 75, 150, 150); + vkvg_clip(ctx); + + vkvg_set_source_rgb(ctx, 0, 1, 0); + vkvg_paint(ctx); + + vkvg_save(ctx); + + vkvg_rectangle(ctx, 100, 100, 100, 100); + vkvg_clip(ctx); + + vkvg_set_source_rgb(ctx, 1, 0, 0); + vkvg_paint(ctx); + + vkvg_set_line_width(ctx, 40); + vkvg_set_source_rgb(ctx, 0, 0, 1); + vkvg_move_to(ctx, 0,0); + vkvg_line_to(ctx, 512,512); + vkvg_stroke_preserve(ctx); + + vkvg_restore(ctx); + vkvg_set_line_width(ctx, 30); + vkvg_set_source_rgb(ctx, 0, 0, 0); + vkvg_stroke_preserve(ctx); + vkvg_restore(ctx); + + vkvg_set_line_width(ctx, 20); + vkvg_set_source_rgb(ctx, 1, 0, 0); + vkvg_stroke_preserve(ctx); + + /*vkvg_restore(ctx); + + vkvg_set_line_width(ctx, 10); + vkvg_set_source_rgb(ctx, 1, 1, 0); + vkvg_stroke(ctx);*/ + + vkvg_destroy(ctx); +} diff --git a/src/vkvg_context.c b/src/vkvg_context.c index 427dd5a..51f3a04 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -56,6 +56,7 @@ void _init_ctx(VkvgContext ctx) { ctx->renderPassBeginInfo.renderArea.extent.width = ctx->pSurf->width; ctx->renderPassBeginInfo.renderArea.extent.height = ctx->pSurf->height; ctx->renderPassBeginInfo.pClearValues = clearValues; + ctx->curClipRef = 0; LOCK_SURFACE(ctx->pSurf) @@ -728,6 +729,7 @@ static const VkClearAttachment clearColorAttach = {VK_IMAGE_ASPECT_COLOR_BIT, 0, void _reset_clip(VkvgContext ctx) { _emit_draw_cmd_undrawn_vertices(ctx); + ctx->curClipRef = 0; if (!ctx->cmdStarted) { // if command buffer is not already started and in a renderpass, we use the renderpass // with the loadop clear for stencil @@ -766,6 +768,7 @@ void vkvg_clear(VkvgContext ctx) { ctx->curClipState = vkvg_clip_state_clear; _emit_draw_cmd_undrawn_vertices(ctx); + ctx->curClipRef = 0; if (!ctx->cmdStarted) { ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearAll; _start_cmd_for_render_pass(ctx); @@ -790,7 +793,7 @@ void _clip_preserve(VkvgContext ctx) { vkh_cmd_label_start(ctx->cmd, "clip", DBG_LAB_COLOR_CLIP); #endif - if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD) { + /*if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD) { _poly_fill(ctx, NULL); CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping); } else { @@ -805,10 +808,20 @@ void _clip_preserve(VkvgContext ctx) { CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); - _draw_full_screen_quad(ctx, NULL); + _draw_full_screen_quad(ctx, NULL);*/ + + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping); + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); + CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); + _fill_non_zero(ctx); + _emit_draw_cmd_undrawn_vertices(ctx); + ctx->curClipRef++; _bind_draw_pipeline(ctx); + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef); CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_ALL_BIT); #if defined(DEBUG) && defined(VKVG_DBG_UTILS) vkh_cmd_label_end(ctx->cmd); @@ -1308,90 +1321,16 @@ void vkvg_save(VkvgContext ctx) { VkvgDevice dev = ctx->dev; vkvg_context_save_t* sav = &ctx->pSavedCtxs[ctx->ctxSaveCount]; - _flush_cmd_buff(ctx); + /*_flush_cmd_buff(ctx); if (!_wait_ctx_flush_end(ctx)) { free(sav); return; - } + }*/ + sav->curClipRef = ctx->curClipRef; if (ctx->curClipState == vkvg_clip_state_clip) { sav->clippingState = vkvg_clip_state_clip_saved; - - uint8_t curSaveStencil = ctx->curSavBit / 6; - - if (ctx->curSavBit > 0 && ctx->curSavBit % 6 == 0) { // new save/restore stencil image have to be created - VkhImage* savedStencilsPtr = ctx->savedStencils; - if (savedStencilsPtr) - savedStencilsPtr = (VkhImage*)realloc(ctx->savedStencils, curSaveStencil * sizeof(VkhImage)); - else - savedStencilsPtr = (VkhImage*)malloc(curSaveStencil * sizeof(VkhImage)); - if (savedStencilsPtr == NULL) { - free(sav); - ctx->status = VKVG_STATUS_NO_MEMORY; - return; - } - ctx->savedStencils = savedStencilsPtr; - VkhImage savStencil = vkh_image_ms_create( - ctx->dev->vkhDev, dev->stencilFormat, ctx->pSurf->surfClass->samples, ctx->pSurf->width, ctx->pSurf->height, - VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); - ctx->savedStencils[curSaveStencil - 1] = savStencil; - - vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - ctx->cmdStarted = true; - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_start(ctx->cmd, "new save/restore stencil", DBG_LAB_COLOR_SAV); -#endif - - vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - vkh_image_set_layout(ctx->cmd, savStencil, dev->stencilAspectFlag, VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - - VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}, - .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}, - .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}}; - vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - vkh_image_get_vkimage(savStencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &cregion); - - vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, dev->stencilAspectFlag, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_end(ctx->cmd); -#endif - - VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd)); - _wait_and_submit_cmd(ctx); - } - - uint8_t curSaveBit = 1 << (ctx->curSavBit % 6 + 2); - - _start_cmd_for_render_pass(ctx); - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_start(ctx->cmd, "save rp", DBG_LAB_COLOR_SAV); -#endif - - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping); - - CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT | curSaveBit); - CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); - CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, curSaveBit); - - _draw_full_screen_quad(ctx, NULL); - - _bind_draw_pipeline(ctx); - CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_end(ctx->cmd); -#endif - ctx->curSavBit++; } else if (ctx->curClipState == vkvg_clip_state_none) sav->clippingState = (_get_previous_clip_state(ctx) & 0x03); else @@ -1421,11 +1360,16 @@ void vkvg_restore(VkvgContext ctx) { vkvg_context_save_t* sav = &ctx->pSavedCtxs[ctx->ctxSaveCount-1]; - _flush_cmd_buff(ctx); + //_flush_cmd_buff(ctx); + _emit_draw_cmd_undrawn_vertices(ctx); + + ctx->curClipRef = sav->curClipRef; + if (ctx->cmdStarted) + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef); if (ctx->curClipState) { //!=none - if (!_wait_ctx_flush_end(ctx)) + /*if (!_wait_ctx_flush_end(ctx)) return; if (ctx->curClipState == vkvg_clip_state_clip && sav->clippingState == vkvg_clip_state_clear) { @@ -1434,7 +1378,7 @@ void vkvg_restore(VkvgContext ctx) { uint8_t curSaveBit = 1 << ((ctx->curSavBit - 1) % 6 + 2); - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil; + //ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil; _start_cmd_for_render_pass(ctx); #if defined(DEBUG) && defined(VKVG_DBG_UTILS) @@ -1459,51 +1403,10 @@ void vkvg_restore(VkvgContext ctx) { _flush_cmd_buff(ctx); if (!_wait_ctx_flush_end(ctx)) return; - } + }*/ } if (sav->clippingState == vkvg_clip_state_clip_saved) { - ctx->curSavBit--; - - uint8_t curSaveStencil = ctx->curSavBit / 6; - if (ctx->curSavBit > 0 && - ctx->curSavBit % 6 == - 0) { // addtional save/restore stencil image have to be copied back to surf stencil first - VkhImage savStencil = ctx->savedStencils[curSaveStencil - 1]; - - vkh_cmd_begin(ctx->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - ctx->cmdStarted = true; - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_start(ctx->cmd, "additional stencil copy while restoring", DBG_LAB_COLOR_SAV); -#endif - - vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - vkh_image_set_layout(ctx->cmd, savStencil, ctx->dev->stencilAspectFlag, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); - VkImageCopy cregion = {.srcSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}, - .dstSubresource = {VK_IMAGE_ASPECT_STENCIL_BIT, 0, 0, 1}, - .extent = {ctx->pSurf->width, ctx->pSurf->height, 1}}; - vkCmdCopyImage(ctx->cmd, vkh_image_get_vkimage(savStencil), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - vkh_image_get_vkimage(ctx->pSurf->stencil), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, - &cregion); - vkh_image_set_layout(ctx->cmd, ctx->pSurf->stencil, ctx->dev->stencilAspectFlag, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); - -#if defined(DEBUG) && defined(VKVG_DBG_UTILS) - vkh_cmd_label_end(ctx->cmd); -#endif - - VK_CHECK_RESULT(vkEndCommandBuffer(ctx->cmd)); - _wait_and_submit_cmd(ctx); - if (!_wait_ctx_flush_end(ctx)) - return; - vkh_image_destroy(savStencil); - } } ctx->curClipState = vkvg_clip_state_none; diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 6b08e35..41a43a4 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -645,7 +645,9 @@ void _start_cmd_for_render_pass(VkvgContext ctx) { _update_push_constants(ctx); _bind_draw_pipeline(ctx); - CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + //CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); + CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, 0xff); + CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, ctx->curClipRef); ctx->cmdStarted = true; } // compute inverse mat used in shader when context matrix has changed diff --git a/src/vkvg_context_internal.h b/src/vkvg_context_internal.h index c22f4bd..79f3bd3 100644 --- a/src/vkvg_context_internal.h +++ b/src/vkvg_context_internal.h @@ -100,6 +100,7 @@ typedef struct _vkvg_context_save_t { VkvgPattern pattern; VkvgFont currentFont; vkvg_clip_state_t clippingState; + uint32_t curClipRef; } vkvg_context_save_t; typedef struct _vkvg_context_t { @@ -197,6 +198,9 @@ typedef struct _vkvg_context_t { uint8_t curSavBit; // current stencil bit used to save context, 6 bits used by stencil for save/restore vkvg_clip_state_t curClipState; // current clipping status relative to the previous saved one or clear state if + uint32_t curClipRef; + uint32_t savedClipOffset; + VkhImage* savedStencils; // additional image for saving contexes once more than 6 save/restore are reached VkRenderPassBeginInfo renderPassBeginInfo; } vkvg_context; diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h index e640266..09df720 100644 --- a/src/vkvg_device_internal.h +++ b/src/vkvg_device_internal.h @@ -7,9 +7,9 @@ #include "vkvg_fonts.h" #include "vkvg_internal.h" -#define STENCIL_FILL_BIT 0x1 -#define STENCIL_CLIP_BIT 0x2 -#define STENCIL_ALL_BIT 0x3 +#define STENCIL_FILL_BIT 1 << 7 +#define STENCIL_CLIP_BIT 0xFF +#define STENCIL_ALL_BIT 0xFF #define VKVG_MAX_CACHED_CONTEXT_COUNT 2 diff --git a/src/vkvg_surface_internal.c b/src/vkvg_surface_internal.c index 3652e33..9483f06 100644 --- a/src/vkvg_surface_internal.c +++ b/src/vkvg_surface_internal.c @@ -268,20 +268,20 @@ void _setupPipelines(surface_class* surf) { STENCIL_CLIP_BIT, STENCIL_FILL_BIT, 0}; - VkStencilOpState clipingOpState = {VK_STENCIL_OP_ZERO, - VK_STENCIL_OP_REPLACE, + VkStencilOpState clipingOpState = {VK_STENCIL_OP_KEEP, + VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, - VK_COMPARE_OP_EQUAL, - STENCIL_FILL_BIT, + VK_COMPARE_OP_LESS_OR_EQUAL, + STENCIL_ALL_BIT, STENCIL_ALL_BIT, - 0x2}; + 0x0}; VkStencilOpState stencilOpState = {VK_STENCIL_OP_KEEP, - VK_STENCIL_OP_ZERO, VK_STENCIL_OP_KEEP, - VK_COMPARE_OP_EQUAL, - STENCIL_FILL_BIT, - STENCIL_FILL_BIT, - 0x1}; + VK_STENCIL_OP_KEEP, + VK_COMPARE_OP_LESS_OR_EQUAL, + STENCIL_ALL_BIT, + STENCIL_ALL_BIT, + 0x0}; VkPipelineDepthStencilStateCreateInfo dsStateCreateInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, @@ -395,11 +395,12 @@ void _setupPipelines(surface_class* surf) { dsStateCreateInfo.back = dsStateCreateInfo.front = stencilOpState; blendAttachmentState.colorWriteMask = 0xf; - dynamicState.dynamicStateCount = 3; + dynamicState.dynamicStateCount = 5; pipelineCreateInfo.stageCount = 2; VK_CHECK_RESULT( vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &surf->pipe_OVER)); + dynamicState.dynamicStateCount = 3; blendAttachmentState.alphaBlendOp = blendAttachmentState.colorBlendOp = VK_BLEND_OP_SUBTRACT; VK_CHECK_RESULT( vkCreateGraphicsPipelines(dev->vkDev, dev->pipelineCache, 1, &pipelineCreateInfo, NULL, &surf->pipe_SUB)); |