summaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-16 13:56:29 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-16 13:56:29 +0200
commit42f7118a6cfc48965410ab52b4e18a466e4082b3 (patch)
treec4b441ff09c8a253accdede23aa6d7b56fe21bf6
parentce0269b31ba948e243cc652dc9b694f004644a94 (diff)
surface class
-rw-r--r--src/vkvg_context.c22
-rw-r--r--src/vkvg_context_internal.c25
-rw-r--r--src/vkvg_device.c21
-rw-r--r--src/vkvg_device_internal.c30
-rw-r--r--src/vkvg_device_internal.h17
-rw-r--r--src/vkvg_surface.c25
-rw-r--r--src/vkvg_surface_internal.c136
-rw-r--r--src/vkvg_surface_internal.h31
-rw-r--r--tests/common/vkengine.c2
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,