diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-16 13:56:29 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-16 13:56:29 +0200 |
| commit | 42f7118a6cfc48965410ab52b4e18a466e4082b3 (patch) | |
| tree | c4b441ff09c8a253accdede23aa6d7b56fe21bf6 | |
| parent | ce0269b31ba948e243cc652dc9b694f004644a94 (diff) | |
surface class
| -rw-r--r-- | src/vkvg_context.c | 22 | ||||
| -rw-r--r-- | src/vkvg_context_internal.c | 25 | ||||
| -rw-r--r-- | src/vkvg_device.c | 21 | ||||
| -rw-r--r-- | src/vkvg_device_internal.c | 30 | ||||
| -rw-r--r-- | src/vkvg_device_internal.h | 17 | ||||
| -rw-r--r-- | src/vkvg_surface.c | 25 | ||||
| -rw-r--r-- | src/vkvg_surface_internal.c | 136 | ||||
| -rw-r--r-- | src/vkvg_surface_internal.h | 31 | ||||
| -rw-r--r-- | tests/common/vkengine.c | 2 |
9 files changed, 178 insertions, 131 deletions
diff --git a/src/vkvg_context.c b/src/vkvg_context.c index e1c8fee..382b121 100644 --- a/src/vkvg_context.c +++ b/src/vkvg_context.c @@ -60,17 +60,17 @@ void _init_ctx(VkvgContext ctx) { LOCK_SURFACE(ctx->pSurf) if (ctx->pSurf->newSurf) { - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->renderPass_ClearAll; + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearAll; ctx->pSurf->newSurf = false; } else { - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->renderPass_ClearStencil; + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil; } UNLOCK_SURFACE(ctx->pSurf); vkvg_surface_reference(ctx->pSurf); - ctx->renderPassBeginInfo.clearValueCount = ctx->pSurf->samples == VK_SAMPLE_COUNT_1_BIT ? 2 : 3; + ctx->renderPassBeginInfo.clearValueCount = ctx->pSurf->surfClass->samples == VK_SAMPLE_COUNT_1_BIT ? 2 : 3; #ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE ctx->timelineStep = 0; @@ -94,7 +94,6 @@ VkvgContext vkvg_create(VkvgSurface surf) { ctx->pSurf = surf; ctx->status = VKVG_STATUS_SUCCESS; _init_ctx(ctx); - _update_descriptor_set(ctx, surf->dev->emptyImg, ctx->dsSrc); _clear_path(ctx); ctx->cmd = ctx->cmdBuffers[0]; // current recording buffer return ctx; @@ -152,7 +151,6 @@ VkvgContext vkvg_create(VkvgSurface surf) { _createDescriptorPool(ctx); _init_descriptor_sets(ctx); _font_cache_update_context_descset(ctx); - _update_descriptor_set(ctx, surf->dev->emptyImg, ctx->dsSrc); _update_gradient_desc_set(ctx); _clear_path(ctx); @@ -745,7 +743,7 @@ void _reset_clip(VkvgContext ctx) { if (!ctx->cmdStarted) { // if command buffer is not already started and in a renderpass, we use the renderpass // with the loadop clear for stencil - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->renderPass_ClearStencil; + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearStencil; // force run of one renderpass (even empty) to perform clear load op _start_cmd_for_render_pass(ctx); return; @@ -781,7 +779,7 @@ void vkvg_clear(VkvgContext ctx) { _emit_draw_cmd_undrawn_vertices(ctx); if (!ctx->cmdStarted) { - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->renderPass_ClearAll; + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass_ClearAll; _start_cmd_for_render_pass(ctx); return; } @@ -806,9 +804,9 @@ void _clip_preserve(VkvgContext ctx) { if (ctx->curFillRule == VKVG_FILL_RULE_EVEN_ODD) { _poly_fill(ctx, NULL); - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipelineClipping); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping); } else { - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipelineClipping); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelineClipping); CmdSetStencilReference(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); CmdSetStencilCompareMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_CLIP_BIT); CmdSetStencilWriteMask(ctx->cmd, VK_STENCIL_FRONT_AND_BACK, STENCIL_FILL_BIT); @@ -1359,7 +1357,7 @@ void vkvg_save(VkvgContext ctx) { } ctx->savedStencils = savedStencilsPtr; VkhImage savStencil = vkh_image_ms_create( - (VkhDevice)&ctx->dev->vkDev, dev->stencilFormat, ctx->pSurf->samples, ctx->pSurf->width, ctx->pSurf->height, + (VkhDevice)&ctx->dev->vkDev, 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; @@ -1403,7 +1401,7 @@ void vkvg_save(VkvgContext ctx) { vkh_cmd_label_start(ctx->cmd, "save rp", DBG_LAB_COLOR_SAV); #endif - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipelineClipping); + 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); @@ -1467,7 +1465,7 @@ void vkvg_restore(VkvgContext ctx) { vkh_cmd_label_start(ctx->cmd, "restore rp", DBG_LAB_COLOR_SAV); #endif - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipelineClipping); + 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, curSaveBit); diff --git a/src/vkvg_context_internal.c b/src/vkvg_context_internal.c index 6f10f76..97f0c43 100644 --- a/src/vkvg_context_internal.c +++ b/src/vkvg_context_internal.c @@ -530,7 +530,7 @@ void _end_render_pass(VkvgContext ctx) { #if defined(DEBUG) && defined(VKVG_DBG_UTILS) vkh_cmd_label_end(ctx->cmd); #endif - ctx->renderPassBeginInfo.renderPass = ctx->pSurf->renderPass; + ctx->renderPassBeginInfo.renderPass = ctx->pSurf->surfClass->renderPass; } void _check_vao_size(VkvgContext ctx) { @@ -607,16 +607,16 @@ void _flush_cmd_buff(VkvgContext ctx) { void _bind_draw_pipeline(VkvgContext ctx) { switch (ctx->curOperator) { case VKVG_OPERATOR_OVER: - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipe_OVER); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipe_OVER); break; case VKVG_OPERATOR_CLEAR: - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipe_CLEAR); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipe_CLEAR); break; case VKVG_OPERATOR_DIFFERENCE: - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipe_SUB); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipe_SUB); break; default: - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipe_OVER); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipe_OVER); break; } } @@ -698,11 +698,10 @@ void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat) { switch (newPatternType) { case VKVG_PATTERN_TYPE_SOLID: _flush_cmd_buff(ctx); - if (!_wait_ctx_flush_end(ctx)) - return; - if (lastPat->type == - VKVG_PATTERN_TYPE_SURFACE) // unbind current source surface by replacing it with empty texture - _update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc); + //if (!_wait_ctx_flush_end(ctx)) + // return; + //if (lastPat->type == VKVG_PATTERN_TYPE_SURFACE) // unbind current source surface by replacing it with empty texture + //_update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc); break; case VKVG_PATTERN_TYPE_SURFACE: { _emit_draw_cmd_undrawn_vertices(ctx); @@ -779,8 +778,8 @@ void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat) { if (!_wait_ctx_flush_end(ctx)) return; - if (lastPat && lastPat->type == VKVG_PATTERN_TYPE_SURFACE) - _update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc); + /*if (lastPat && lastPat->type == VKVG_PATTERN_TYPE_SURFACE) + _update_descriptor_set(ctx, ctx->dev->emptyImg, ctx->dsSrc);*/ vec4 bounds = {{(float)ctx->pSurf->width}, {(float)ctx->pSurf->height}, @@ -1602,7 +1601,7 @@ void _poly_fill(VkvgContext ctx, vec4* bounds) { _ensure_renderpass_is_started(ctx); } - CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->pipelinePolyFill); + CmdBindPipeline(ctx->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pSurf->surfClass->pipelinePolyFill); Vertex v = {{0}, ctx->curColor, {0, 0, -1}}; uint32_t ptrPath = 0; diff --git a/src/vkvg_device.c b/src/vkvg_device.c index cf81b98..c0cf94b 100644 --- a/src/vkvg_device.c +++ b/src/vkvg_device.c @@ -109,8 +109,6 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t* info) { _fonts_cache_create(dev, info->fontsDirectories); _device_createDescriptorSetLayout(dev); - _device_create_empty_texture(dev, format, dev->supportedTiling); - if (dev->threadAware) { mtx_init(&dev->mutex, mtx_plain); mtx_init(&dev->fontCache->mutex, mtx_plain); @@ -130,12 +128,6 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t* info) { vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont, "DSLayout FONT"); vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslGrad, "DSLayout GRADIENT"); vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)dev->pipelineLayout, "PLLayout dev"); - - vkh_image_set_name(dev->emptyImg, "empty IMG"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(dev->emptyImg), - "empty IMG VIEW"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(dev->emptyImg), - "empty IMG SAMPLER"); #endif #endif dev->status = VKVG_STATUS_SUCCESS; @@ -229,13 +221,13 @@ const void* vkvg_get_device_requirements(VkPhysicalDeviceFeatures* pEnabledFeatu static VkPhysicalDeviceVulkan12Features enabledFeatures12 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES #ifdef VKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT - , - .scalarBlockLayout = VK_TRUE + ,.scalarBlockLayout = VK_TRUE #endif #ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE , .timelineSemaphore = VK_TRUE #endif + ,.descriptorBindingPartiallyBound = VK_TRUE }; enabledFeatures12.pNext = pNext; pNext = &enabledFeatures12; @@ -342,7 +334,7 @@ VkvgDevice vkvg_device_create(vkvg_device_create_info_t* info) { } VkPhysicalDeviceFeatures enabledFeatures = {0}; - const void* pNext = vkvg_get_device_requirements(&enabledFeatures); + const void* pNext = vkvg_get_device_requirements(&enabledFeatures); VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .queueCreateInfoCount = qCount, @@ -364,6 +356,8 @@ VkvgDevice vkvg_device_create(vkvg_device_create_info_t* info) { _device_init(dev, info); + dev->surfaceClasses = array_create_SurfaceClass(2); + atomic_init(&dev->references, 1); return dev; @@ -393,7 +387,10 @@ void vkvg_device_destroy(VkvgDevice dev) { vkDeviceWaitIdle(dev->vkDev); - vkh_image_destroy(dev->emptyImg); + for (int i = 0; i < dev->surfaceClasses.count; ++i) { + //_surface_class_destroy (dev->surfaceClasses.elements[i]); + } + array_destroy_SurfaceClass(&dev->surfaceClasses); vkDestroyDescriptorSetLayout(dev->vkDev, dev->dslGrad, NULL); vkDestroyDescriptorSetLayout(dev->vkDev, dev->dslFont, NULL); diff --git a/src/vkvg_device_internal.c b/src/vkvg_device_internal.c index c3e61bc..918526c 100644 --- a/src/vkvg_device_internal.c +++ b/src/vkvg_device_internal.c @@ -73,11 +73,22 @@ void _device_create_pipeline_cache(VkvgDevice dev) { } void _device_createDescriptorSetLayout(VkvgDevice dev) { + VkDescriptorBindingFlags bindingFlags[] = { + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT // Allows empty/unbound slots in this binding + }; + VkDescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .bindingCount = 1, + .pBindingFlags = bindingFlags + }; VkDescriptorSetLayoutBinding dsLayoutBinding = {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL}; VkDescriptorSetLayoutCreateInfo dsLayoutCreateInfo = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, .bindingCount = 1, .pBindings = &dsLayoutBinding}; + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pNext = &bindingFlagsInfo, + .bindingCount = 1, + .pBindings = &dsLayoutBinding}; VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslFont)); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(dev->vkDev, &dsLayoutCreateInfo, NULL, &dev->dslSrc)); dsLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -189,23 +200,6 @@ bool _device_init_function_pointers(VkvgDevice dev) { return true; } -void _device_create_empty_texture(VkvgDevice dev, VkFormat format, VkImageTiling tiling) { - // create empty image to bind to context source descriptor when not in use - dev->emptyImg = vkh_image_create((VkhDevice)&dev->vkDev, format, 16, 16, tiling, VKH_MEMORY_USAGE_GPU_ONLY, - VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); - vkh_image_create_descriptor(dev->emptyImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST, - VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - - _device_wait_and_reset_device_fence(dev); - - vkh_cmd_begin(dev->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); - vkh_image_set_layout(dev->cmd, dev->emptyImg, VK_IMAGE_ASPECT_COLOR_BIT, 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); - _device_submit_cmd(dev, &dev->cmd, dev->fence); -} void _device_check_best_image_tiling(VkvgDevice dev, VkFormat format) { VkFlags stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}; diff --git a/src/vkvg_device_internal.h b/src/vkvg_device_internal.h index 03574d3..eb47780 100644 --- a/src/vkvg_device_internal.h +++ b/src/vkvg_device_internal.h @@ -58,6 +58,11 @@ typedef struct _cached_ctx { struct _cached_ctx* pNext; } _cached_ctx; +typedef struct _surface_class* SurfaceClass; + +CTOR_ARRAY(SurfaceClass) +ARRAY_DEL_ELT(SurfaceClass) + typedef struct _vkvg_device_t { vkvg_status_t status; /**< Current status of device, affected by last operation */ VkDevice vkDev; /**< Vulkan Logical Device */ @@ -93,7 +98,6 @@ typedef struct _vkvg_device_t { VkhDevice vkhDev; /**< old VkhDev created during vulkan context creation by @ref vkvg_device_create. */ - VkhImage emptyImg; /**< prevent unbound descriptor to trigger Validation error 61 */ bool deferredResolve; /**< if true, resolve only on context destruction and set as source */ _font_cache_t* fontCache; /**< Store everything relative to common font caching system */ @@ -112,6 +116,7 @@ typedef struct _vkvg_device_t { #if VKVG_DBG_STATS vkvg_debug_stats_t debug_stats; /**< debug statistics on memory usage and vulkan ressources */ #endif + array_SurfaceClass surfaceClasses; } vkvg_device; #define LOCK_DEVICE \ @@ -130,11 +135,11 @@ void _device_create_pipeline_cache(VkvgDevice dev); VkRenderPass _device_createRenderPassMS(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp); VkRenderPass _device_createRenderPassNoResolve(VkvgDevice dev, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp); -void _device_setupPipelines(VkvgDevice dev); -void _device_createDescriptorSetLayout(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 _device_setupPipelines(VkvgDevice dev); +void _device_createDescriptorSetLayout(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); bool _device_try_get_cached_context(VkvgDevice dev, VkvgContext* pCtx); void _device_store_context(VkvgContext ctx); diff --git a/src/vkvg_surface.c b/src/vkvg_surface.c index 6d10df8..bb8ab1c 100644 --- a/src/vkvg_surface.c +++ b/src/vkvg_surface.c @@ -40,7 +40,7 @@ void vkvg_surface_clear(VkvgSurface surf) { } VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height) { - VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); + VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT, VK_SAMPLE_COUNT_1_BIT); if (surf->status) return surf; @@ -55,7 +55,7 @@ VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height) return surf; } VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void* vkhImg) { - VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); + VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT, VK_SAMPLE_COUNT_1_BIT); if (surf->status) return surf; @@ -84,7 +84,7 @@ VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void* vkhImg) { } // TODO: it would be better to blit in original size and create ms final image with dest surf dims VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char* img, uint32_t width, uint32_t height) { - VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT); + VkvgSurface surf = _create_surface(dev, FB_COLOR_FORMAT, VK_SAMPLE_COUNT_1_BIT); if (surf->status) return surf; if (!img || width <= 0 || height <= 0) { @@ -105,7 +105,7 @@ VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char* img, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); // bgra bliting target VkhImage tmpImg = - vkh_image_create((VkhDevice)&surf->dev->vkDev, surf->format, surf->width, surf->height, VK_IMAGE_TILING_LINEAR, + vkh_image_create((VkhDevice)&surf->dev->vkDev, surf->surfClass->format, surf->width, surf->height, VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); vkh_image_create_descriptor(tmpImg, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, @@ -214,25 +214,12 @@ void vkvg_surface_destroy(VkvgSurface surf) { VkvgDevice dev = surf->dev; -#ifndef __APPLE__ - vkDestroyPipeline(dev->vkDev, surf->pipelinePolyFill, NULL); -#endif - vkDestroyPipeline(dev->vkDev, surf->pipelineClipping, NULL); + _destroy_surface_class (surf->surfClass); - vkDestroyPipeline(dev->vkDev, surf->pipe_OVER, NULL); - vkDestroyPipeline(dev->vkDev, surf->pipe_SUB, NULL); - vkDestroyPipeline(dev->vkDev, surf->pipe_CLEAR, NULL); -#ifdef VKVG_WIRED_DEBUG - vkDestroyPipeline(dev->vkDev, surf->pipelineWired, NULL); - vkDestroyPipeline(dev->vkDev, surf->pipelineLineList, NULL); -#endif vkDestroyCommandPool(surf->dev->vkDev, surf->cmdPool, NULL); vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL); - vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass, NULL); - vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass_ClearStencil, NULL); - vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass_ClearAll, NULL); if (!surf->img->imported) vkh_image_destroy(surf->img); @@ -282,7 +269,7 @@ void vkvg_surface_resolve(VkvgSurface surf) { VkFormat vkvg_surface_get_vk_format(VkvgSurface surf) { if (vkvg_surface_status(surf)) return VK_FORMAT_UNDEFINED; - return surf->format; + return surf->surfClass->format; } uint32_t vkvg_surface_get_width(VkvgSurface surf) { if (vkvg_surface_status(surf)) diff --git a/src/vkvg_surface_internal.c b/src/vkvg_surface_internal.c index 2c794f6..5b56db9 100644 --- a/src/vkvg_surface_internal.c +++ b/src/vkvg_surface_internal.c @@ -94,7 +94,7 @@ void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect) { VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; VkhImage img = surf->imgMS; - if (surf->samples == VK_SAMPLE_COUNT_1_BIT) + if (surf->surfClass->samples == VK_SAMPLE_COUNT_1_BIT) img = surf->img; vkh_image_set_layout(cmd, img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -128,7 +128,7 @@ void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect) { UNLOCK_SURFACE(surf) } -VkRenderPass _createRenderPassNoResolve(VkvgSurface surf, VkAttachmentLoadOp loadOp, +VkRenderPass _createRenderPassNoResolve(surface_class* surf, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) { VkAttachmentDescription attColor = {.format = FB_COLOR_FORMAT, .samples = surf->samples, @@ -176,7 +176,7 @@ VkRenderPass _createRenderPassNoResolve(VkvgSurface surf, VkAttachmentLoadOp loa VK_CHECK_RESULT(vkCreateRenderPass(surf->dev->vkDev, &renderPassInfo, NULL, &rp)); return rp; } -VkRenderPass _createRenderPassMS(VkvgSurface surf, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) { +VkRenderPass _createRenderPassMS(surface_class* surf, VkAttachmentLoadOp loadOp, VkAttachmentLoadOp stencilLoadOp) { VkAttachmentDescription attColor = {.format = FB_COLOR_FORMAT, .samples = surf->samples, .loadOp = loadOp, @@ -233,7 +233,7 @@ VkRenderPass _createRenderPassMS(VkvgSurface surf, VkAttachmentLoadOp loadOp, Vk VK_CHECK_RESULT(vkCreateRenderPass(surf->dev->vkDev, &renderPassInfo, NULL, &rp)); return rp; } -void _setupPipelines(VkvgSurface surf) { +void _setupPipelines(surface_class* surf) { VkvgDevice dev = surf->dev; VkGraphicsPipelineCreateInfo pipelineCreateInfo = {.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .renderPass = surf->renderPass}; @@ -457,7 +457,7 @@ void _setupPipelines(VkvgSurface surf) { void _create_surface_main_image(VkvgSurface surf) { VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev; - surf->img = vkh_image_create(vkhd, surf->format, surf->width, surf->height, surf->dev->supportedTiling, + surf->img = vkh_image_create(vkhd, surf->surfClass->format, surf->width, surf->height, surf->dev->supportedTiling, VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT); @@ -475,9 +475,9 @@ void _create_surface_main_image(VkvgSurface surf) { // create multisample color img if sample count > 1 and the stencil buffer multisampled or not void _create_surface_secondary_images(VkvgSurface surf) { VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev; - if (surf->samples > VK_SAMPLE_COUNT_1_BIT) { + if (surf->surfClass->samples > VK_SAMPLE_COUNT_1_BIT) { surf->imgMS = vkh_image_ms_create( - vkhd, surf->format, surf->samples, surf->width, surf->height, VKH_MEMORY_USAGE_GPU_ONLY, + vkhd, surf->surfClass->format, surf->surfClass->samples, surf->width, surf->height, VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); vkh_image_create_descriptor(surf->imgMS, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST, @@ -490,7 +490,7 @@ void _create_surface_secondary_images(VkvgSurface surf) { "SURF MS color SAMPLER"); #endif } - surf->stencil = vkh_image_ms_create(vkhd, surf->dev->stencilFormat, surf->samples, surf->width, surf->height, + surf->stencil = vkh_image_ms_create(vkhd, surf->dev->stencilFormat, surf->surfClass->samples, surf->width, surf->height, VKH_MEMORY_USAGE_GPU_ONLY, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); @@ -512,13 +512,13 @@ void _create_framebuffer(VkvgSurface surf) { vkh_image_get_view(surf->imgMS), }; VkFramebufferCreateInfo frameBufferCreateInfo = {.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = surf->renderPass, + .renderPass = surf->surfClass->renderPass, .attachmentCount = 3, .pAttachments = attachments, .width = surf->width, .height = surf->height, .layers = 1}; - if (surf->samples == VK_SAMPLE_COUNT_1_BIT) + if (surf->surfClass->samples == VK_SAMPLE_COUNT_1_BIT) frameBufferCreateInfo.attachmentCount = 2; else if (surf->dev->deferredResolve) { attachments[0] = attachments[2]; @@ -541,30 +541,19 @@ void _create_surface_images(VkvgSurface surf) { vkh_image_set_name(surf->stencil, "surfStencil"); #endif } -VkvgSurface _create_surface(VkvgDevice dev, VkFormat format) { - LOG(VKVG_LOG_INFO, "CREATE Surface\n"); - if (vkvg_device_status(dev)) { - LOGE("CREATE Surface failed, invalid Device\n"); - return (VkvgSurface)&_vkvg_status_device_error; - } - VkvgSurface surf = (vkvg_surface*)calloc(1, sizeof(vkvg_surface)); +surface_class* _create_surface_class (VkvgDevice dev, VkFormat format, VkSampleCountFlags samples) { + surface_class* surf = (surface_class*)calloc(1, sizeof(surface_class)); if (!surf) { - LOGE("CREATE Surface failed, no memory\n"); - return (VkvgSurface)&_vkvg_status_no_memory; + LOGE("CREATE Surface class failed, no memory\n"); + return NULL; } - atomic_init(&surf->references, 1); + VkhDevice vkhd = (VkhDevice)&dev->vkDev; + surf->dev = dev; surf->format = format; - surf->hdpi = 72; - surf->vdpi = 72; - surf->samples = VK_SAMPLE_COUNT_1_BIT; - - if (dev->threadAware) - mtx_init(&surf->mutex, mtx_plain); - - VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev; + surf->samples = samples; if (dev->deferredResolve || surf->samples == VK_SAMPLE_COUNT_1_BIT) { surf->renderPass = @@ -584,10 +573,90 @@ VkvgSurface _create_surface(VkvgDevice dev, VkFormat format) { _setupPipelines(surf); +#if defined(DEBUG) && defined(VKVG_DBG_UTILS) + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass, "RP load img/stencil"); + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass_ClearStencil, "RP clear stencil"); + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass_ClearAll, "RP clear all"); +#ifndef __APPLE__ + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipelinePolyFill, "PL Poly fill"); +#endif + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipelineClipping, "PL Clipping"); + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_OVER, "PL draw Over"); + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_SUB, "PL draw Substract"); + vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_CLEAR, "PL draw Clear"); +#endif + + atomic_init(&surf->references, 1); + return surf; +} + +surface_class* _get_surface_class (VkvgDevice dev, VkFormat format, VkSampleCountFlags samples) { + for (int i = 0; i < dev->surfaceClasses.count; ++i) { + surface_class* sc = dev->surfaceClasses.elements[i]; + if (sc->format == format && sc->samples == samples) { + atomic_fetch_add_explicit(&sc->references, 1, memory_order_relaxed); + return sc; + } + } + return _create_surface_class (dev, format, samples); +} +void _destroy_surface_class (surface_class* surf) { + if (atomic_fetch_sub_explicit(&surf->references, 1, memory_order_acq_rel) != 1) + return; + + LOG(VKVG_LOG_INFO, "DESTROY Surface class.\n"); + + VkvgDevice dev = surf->dev; + array_del_SurfaceClass(&dev->surfaceClasses, surf); + +#ifndef __APPLE__ + vkDestroyPipeline(dev->vkDev, surf->pipelinePolyFill, NULL); +#endif + vkDestroyPipeline(dev->vkDev, surf->pipelineClipping, NULL); + + vkDestroyPipeline(dev->vkDev, surf->pipe_OVER, NULL); + vkDestroyPipeline(dev->vkDev, surf->pipe_SUB, NULL); + vkDestroyPipeline(dev->vkDev, surf->pipe_CLEAR, NULL); + +#ifdef VKVG_WIRED_DEBUG + vkDestroyPipeline(dev->vkDev, surf->pipelineWired, NULL); + vkDestroyPipeline(dev->vkDev, surf->pipelineLineList, NULL); +#endif + + vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass, NULL); + vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass_ClearStencil, NULL); + vkDestroyRenderPass(surf->dev->vkDev, surf->renderPass_ClearAll, NULL); + + free(surf); +} + +VkvgSurface _create_surface(VkvgDevice dev, VkFormat format, VkSampleCountFlags samples) { + LOG(VKVG_LOG_INFO, "CREATE Surface\n"); + if (vkvg_device_status(dev)) { + LOGE("CREATE Surface failed, invalid Device\n"); + return (VkvgSurface)&_vkvg_status_device_error; + } + + VkvgSurface surf = (vkvg_surface*)calloc(1, sizeof(vkvg_surface)); + if (!surf) { + LOGE("CREATE Surface failed, no memory\n"); + return (VkvgSurface)&_vkvg_status_no_memory; + } + + surf->dev = dev; + surf->hdpi = 72; + surf->vdpi = 72; + + if (dev->threadAware) + mtx_init(&surf->mutex, mtx_plain); + + VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev; surf->cmdPool = vkh_cmd_pool_create(vkhd, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT); vkh_cmd_buffs_create(vkhd, surf->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &surf->cmd); + surf->surfClass = _get_surface_class (dev, format, samples); + #if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE surf->timeline = vkh_timeline_create(vkhd, 0); #else @@ -596,18 +665,9 @@ VkvgSurface _create_surface(VkvgDevice dev, VkFormat format) { #if defined(DEBUG) && defined(VKVG_DBG_UTILS) vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass, "RP load img/stencil"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass_ClearStencil, "RP clear stencil"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)surf->renderPass_ClearAll, "RP clear all"); -#ifndef __APPLE__ - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipelinePolyFill, "PL Poly fill"); #endif - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipelineClipping, "PL Clipping"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_OVER, "PL draw Over"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_SUB, "PL draw Substract"); - vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)surf->pipe_CLEAR, "PL draw Clear"); -#endif + atomic_init(&surf->references, 1); vkvg_device_reference(surf->dev); return surf; } diff --git a/src/vkvg_surface_internal.h b/src/vkvg_surface_internal.h index 2c2af93..1af9034 100644 --- a/src/vkvg_surface_internal.h +++ b/src/vkvg_surface_internal.h @@ -26,13 +26,27 @@ #include "vkvg.h" #include "vkh.h" +typedef struct _surface_class { + atomic_int references; + VkvgDevice dev; + VkFormat format; + VkSampleCountFlags samples; /**< samples count */ + 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*/ + VkPipeline pipe_OVER; /**< default operator */ + VkPipeline pipe_SUB; + VkPipeline pipe_CLEAR; /**< clear operator */ + VkPipeline pipelinePolyFill; /**< even-odd polygon filling first step */ + VkPipeline pipelineClipping; /**< draw on stencil to update clipping regions */ +} surface_class; + typedef struct _vkvg_surface_t { vkvg_status_t status; /**< Current status of surface, affected by last operation */ atomic_int references; VkvgDevice dev; uint32_t width; uint32_t height; - VkFormat format; VkFramebuffer fb; VkhImage img; VkhImage imgMS; @@ -49,15 +63,7 @@ typedef struct _vkvg_surface_t { #endif int hdpi, /**< only used for FreeType fonts and svg loading */ vdpi; - VkSampleCountFlags samples; /**< samples count */ - 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*/ - VkPipeline pipe_OVER; /**< default operator */ - VkPipeline pipe_SUB; - VkPipeline pipe_CLEAR; /**< clear operator */ - VkPipeline pipelinePolyFill; /**< even-odd polygon filling first step */ - VkPipeline pipelineClipping; /**< draw on stencil to update clipping regions */ + surface_class * surfClass; } vkvg_surface; #define LOCK_SURFACE(surf) \ @@ -76,8 +82,9 @@ void _create_surface_main_image(VkvgSurface surf); void _create_surface_secondary_images(VkvgSurface surf); void _create_framebuffer(VkvgSurface surf); void _create_surface_images(VkvgSurface surf); -VkvgSurface _create_surface(VkvgDevice dev, VkFormat format); +VkvgSurface _create_surface(VkvgDevice dev, VkFormat format, VkSampleCountFlags samples); +void _surface_submit_cmd(VkvgSurface surf); -void _surface_submit_cmd(VkvgSurface surf); +void _destroy_surface_class (surface_class* surf); // bool _surface_wait_cmd (VkvgSurface surf); #endif diff --git a/tests/common/vkengine.c b/tests/common/vkengine.c index 8bb10b7..7830b2e 100644 --- a/tests/common/vkengine.c +++ b/tests/common/vkengine.c @@ -195,7 +195,7 @@ vk_engine_t* vkengine_create(VkPhysicalDeviceType preferedGPU, VkPresentModeKHR TRY_LOAD_DEVICE_EXT(VK_KHR_swapchain) VkPhysicalDeviceFeatures enabledFeatures = {0}; - const void* pNext = vkvg_get_device_requirements(&enabledFeatures); + const void* pNext = vkvg_get_device_requirements(&enabledFeatures); VkDeviceCreateInfo device_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .queueCreateInfoCount = qCount, |