]> O.S.I.I.S - jp/vkvg.git/commitdiff
gunit tests + error handling improvments
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Mon, 25 Nov 2024 13:54:54 +0000 (14:54 +0100)
committerj-p <jp_bruyere@hotmail.com>
Mon, 24 Mar 2025 18:12:00 +0000 (19:12 +0100)
30 files changed:
CMakeLists.txt
doc/design/error_handling.md [new file with mode: 0644]
gunit_tests/CMakeLists.txt [new file with mode: 0644]
gunit_tests/context.cpp [new file with mode: 0644]
gunit_tests/device.cpp [new file with mode: 0644]
gunit_tests/main.cpp [new file with mode: 0644]
gunit_tests/main2.cpp [new file with mode: 0644]
gunit_tests/surface.cpp [new file with mode: 0644]
include/vkvg.h
shaders/vkvg_main.frag
src/cross_os.h
src/shaders.h
src/vkvg_context.c
src/vkvg_context_internal.c
src/vkvg_device.c
src/vkvg_device_internal.c
src/vkvg_device_internal.h
src/vkvg_fonts.c
src/vkvg_internal.h
src/vkvg_pattern.c
src/vkvg_surface.c
src/vkvg_surface_internal.c
src/vkvg_surface_internal.h
tests/common/test.c
tests/data/blender_icons16.png [new file with mode: 0644]
tests/multithreading/multithreaded.c
tests/multithreading/multithreaded2.c
tests/multithreading/threaded_create_surf.c
tests/multithreading/threaded_text.c
tests/pattern_transforms.c

index 1f79c2968a0ee132fe9d0af57c8dddf4e177dee4..1723646812390be365037c7c5256ecc5839122da 100644 (file)
@@ -48,6 +48,9 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
        OPTION(VKVG_WIRED_FILL "enable wired polygon draw to check vertices and primitives" OFF)
        IF (UNIX)
                ADD_COMPILE_OPTIONS(-Wall -Wno-extra -Wno-unknown-pragmas -Wno-missing-braces -Wno-unused-variable -Wno-switch -Wno-unused-value)
+                IF (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+                    ADD_COMPILE_OPTIONS(-g3) # include macro info in debug
+                ENDIF()
        ELSEIF(MSVC)
                ADD_COMPILE_OPTIONS(/TC /W4 /wd4201 /wd4204 /wd4221 /wd4100) # c11 compliant
        ENDIF()
@@ -59,22 +62,27 @@ ELSE()
        IF (ANDROID)
                ADD_COMPILE_OPTIONS(-O3 -w -pedantic)
        ELSEIF (UNIX)           
-               #ADD_COMPILE_OPTIONS(-O3 -w -pedantic -fvisibility=hidden -fno-rtti)
-               #ADD_COMPILE_OPTIONS(-flto -pthread -lpthread -Wl,--no-as-needed)
+            #ADD_COMPILE_OPTIONS(-O3 -w -pedantic -fvisibility=hidden -fno-rtti)
+            #ADD_COMPILE_OPTIONS(-flto -pthread -lpthread -Wl,--no-as-needed)
        ELSEIF(MSVC)
                ADD_COMPILE_OPTIONS(/O2 /TC /W0 /Od)
        ENDIF()
 ENDIF()
 
 OPTION(ENABLE_PROFILING "compile with the -pg options..." OFF)
+OPTION(ENABLE_GTESTS "enable google unit tests" ON)
+
+IF(ENABLE_GTESTS)
+    ADD_SUBDIRECTORY (gunit_tests)
+ENDIF()
 
 IF (ENABLE_PROFILING)
-       ADD_COMPILE_OPTIONS(
-               -pg -fno-reorder-functions -fno-inline
-               -O1
-               -fthread-jumps
-               -falign-functions  -falign-jumps
-               -falign-loops  -falign-labels)
+    ADD_COMPILE_OPTIONS(
+        -pg -fno-reorder-functions -fno-inline
+        -O1
+        -fthread-jumps
+        -falign-functions  -falign-jumps
+        -falign-loops  -falign-labels)
 ENDIF()
 
 OPTION(VKVG_RECORDING "enable experimental recording functions" OFF)
@@ -87,7 +95,7 @@ ENDIF ()
 
 OPTION(VKVG_DBG_STATS "record contexts statistics in the device" OFF)
 IF (VKVG_DBG_STATS)
-       ADD_DEFINITIONS (-DVKVG_DBG_STATS)
+    ADD_DEFINITIONS (-DVKVG_DBG_STATS)
 ENDIF ()
 
 OPTION(VKVG_USE_GLUTESS "Fill non-zero with glu tesselator" ON)
@@ -95,7 +103,7 @@ OPTION(VKVG_USE_GLUTESS "Fill non-zero with glu tesselator" ON)
 CMAKE_DEPENDENT_OPTION(VKVG_SVG "render svg with vkvg-svg library" OFF "UNIX" OFF)
 
 IF (NOT TARGET vkh)
-       ADD_SUBDIRECTORY (vkh)
+    ADD_SUBDIRECTORY (vkh)
 ENDIF()
 
 #use c++ vulkan memory allocator library (https://gpuopen.com/vulkan-memory-allocator/)
diff --git a/doc/design/error_handling.md b/doc/design/error_handling.md
new file mode 100644 (file)
index 0000000..9334434
--- /dev/null
@@ -0,0 +1,13 @@
+#  Error handling strategy
+
+API calls must be safe, even if rendering failed. This means that any call to any api command with any parameter should not result in a program halt. Only current status should be affected by errors.
+
+## Per object status.
+
+Internally, statuses are first checked for each function calls. If objects are in error, api calls will safely return without performing any action.
+The Status field in each vkvg structure being the first member, even a memory allocation failure may return a safe pointer holding only a pointer to VKVG_STATUS_NO_MEMORY static value.
+
+Client applications may check current statuses at anytime, even on a null pointer, to ensure normal operations.
+
+
+
diff --git a/gunit_tests/CMakeLists.txt b/gunit_tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d497d5c
--- /dev/null
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 3.14)
+project(unit_tests)
+
+# GoogleTest requires at least C++14
+set(CMAKE_CXX_STANDARD 14)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+include(FetchContent)
+
+FetchContent_Declare(
+  googletest
+  GIT_REPOSITORY https://github.com/google/googletest.git
+  GIT_TAG        b514bdc898e2951020cbdca1304b75f5950d1f59 #v1.15.2
+)
+
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+FetchContent_MakeAvailable(googletest)
+
+add_executable("${PROJECT_NAME}"
+  main.cpp
+  device.cpp
+  surface.cpp
+  context.cpp
+)
+target_include_directories("${PROJECT_NAME}" PUBLIC
+  "${CMAKE_SOURCE_DIR}/include"
+)
+target_link_libraries(
+  "${PROJECT_NAME}"
+  GTest::gtest_main
+  vkvg
+)
+
+include(GoogleTest)
+gtest_discover_tests("${PROJECT_NAME}")
diff --git a/gunit_tests/context.cpp b/gunit_tests/context.cpp
new file mode 100644 (file)
index 0000000..e44a3d7
--- /dev/null
@@ -0,0 +1,72 @@
+#include "vkvg.h"
+#include <gtest/gtest.h>
+
+// The fixture for testing class Foo.
+class ContextTest : public testing::Test {
+  public:
+    VkvgDevice  dev;
+    VkvgSurface surf;
+
+  protected:
+    // You can remove any or all of the following functions if their bodies would
+    // be empty.
+
+    ContextTest() {
+        vkvg_device_create_info_t info{};
+        dev  = vkvg_device_create(&info);
+        surf = vkvg_surface_create(dev, 512, 512);
+    }
+
+    ~ContextTest() override {
+        vkvg_surface_destroy(surf);
+        vkvg_device_destroy(dev);
+    }
+
+    void SetUp() override {}
+
+    void TearDown() override {}
+};
+
+TEST_F(ContextTest, CtxCreate) {
+    EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_status(NULL));
+
+    VkvgContext ctx = vkvg_create(NULL);
+    EXPECT_EQ(VKVG_STATUS_INVALID_SURFACE, vkvg_status(ctx));
+    vkvg_destroy(ctx);
+
+    ctx = vkvg_create(surf);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_status(ctx));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+
+    vkvg_destroy(ctx);
+}
+
+TEST_F(ContextTest, CtxReference) {
+    EXPECT_EQ(0, vkvg_get_reference_count(NULL));
+
+    VkvgContext ctx = vkvg_create(NULL);
+    EXPECT_EQ(0, vkvg_get_reference_count(ctx));
+
+    ctx = vkvg_create(surf);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_status(ctx));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+
+    EXPECT_EQ(1, vkvg_get_reference_count(ctx));
+    EXPECT_EQ(2, vkvg_surface_get_reference_count(surf));
+    EXPECT_EQ(2, vkvg_device_get_reference_count(dev));
+
+    vkvg_reference(ctx);
+    EXPECT_EQ(2, vkvg_get_reference_count(ctx));
+
+    vkvg_destroy(ctx);
+    EXPECT_EQ(1, vkvg_get_reference_count(ctx));
+
+    vkvg_destroy(ctx);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+    EXPECT_EQ(0, vkvg_get_reference_count(ctx));
+    EXPECT_EQ(1, vkvg_surface_get_reference_count(surf));
+    EXPECT_EQ(2, vkvg_device_get_reference_count(dev));
+}
diff --git a/gunit_tests/device.cpp b/gunit_tests/device.cpp
new file mode 100644 (file)
index 0000000..bce3fea
--- /dev/null
@@ -0,0 +1,49 @@
+#include "vkvg.h"
+#include <gtest/gtest.h>
+
+TEST(Device, CreateNullInfo) {
+    EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_device_status(NULL));
+
+    VkvgDevice dev = vkvg_device_create(NULL);
+    EXPECT_EQ(VKVG_STATUS_INVALID_DEVICE_CREATE_INFO, vkvg_device_status(dev));
+    vkvg_device_destroy(dev);
+}
+TEST(Device, CreateEmpty) {
+    vkvg_device_create_info_t info{};
+    VkvgDevice                dev = vkvg_device_create(&info);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    vkvg_device_destroy(dev);
+}
+
+TEST(Device, Reference) {
+    VkvgDevice dev = vkvg_device_create(NULL);
+    EXPECT_EQ(0, vkvg_device_get_reference_count(dev));
+    vkvg_device_reference(dev);
+
+    vkvg_device_create_info_t info{};
+    dev = vkvg_device_create(&info);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(1, vkvg_device_get_reference_count(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+
+    vkvg_device_reference(dev);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(2, vkvg_device_get_reference_count(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+
+    vkvg_device_destroy(dev);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(1, vkvg_device_get_reference_count(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+
+    vkvg_device_destroy(dev);
+    EXPECT_EQ(0, vkvg_device_get_reference_count(dev));
+}
+
+/*TEST(Device, GetVulkanRequirements)
+{
+
+    vkvg_public void vkvg_get_required_instance_extensions(const char **pExtensions, uint32_t *pExtCount);
+    vkvg_public vkvg_status_t vkvg_get_required_device_extensions(VkPhysicalDevice phy, const char **pExtensions,
+    vkvg_public const void *vkvg_get_device_requirements(VkPhysicalDeviceFeatures *pEnabledFeatures);
+}*/
diff --git a/gunit_tests/main.cpp b/gunit_tests/main.cpp
new file mode 100644 (file)
index 0000000..64becff
--- /dev/null
@@ -0,0 +1,6 @@
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/gunit_tests/main2.cpp b/gunit_tests/main2.cpp
new file mode 100644 (file)
index 0000000..82ceaab
--- /dev/null
@@ -0,0 +1,11 @@
+#include <gtest/gtest.h>
+
+// Demonstrate some basic assertions.
+TEST(HelloTest, BasicAssertions) {
+  // Expect two strings not to be equal.
+  EXPECT_STRNE("hello", "world");
+  // Expect equality.
+  EXPECT_EQ(7 * 6, 42);
+}
+
+
diff --git a/gunit_tests/surface.cpp b/gunit_tests/surface.cpp
new file mode 100644 (file)
index 0000000..f4284d7
--- /dev/null
@@ -0,0 +1,67 @@
+#include "vkvg.h"
+#include <gtest/gtest.h>
+
+// The fixture for testing class Foo.
+class SurfaceTest : public testing::Test {
+  public:
+    VkvgDevice dev;
+
+  protected:
+    // You can remove any or all of the following functions if their bodies would
+    // be empty.
+
+    SurfaceTest() {
+        vkvg_device_create_info_t info{};
+        dev = vkvg_device_create(&info);
+    }
+
+    ~SurfaceTest() override { vkvg_device_destroy(dev); }
+
+    void SetUp() override {}
+
+    void TearDown() override {}
+};
+
+TEST_F(SurfaceTest, SurfCreate) {
+    EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_surface_status(NULL));
+
+    VkvgSurface surf = vkvg_surface_create(NULL, 0, 0);
+
+    EXPECT_EQ(VKVG_STATUS_DEVICE_ERROR, vkvg_surface_status(surf));
+
+    surf = vkvg_surface_create(dev, 512, 512);
+
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+
+    vkvg_surface_destroy(surf);
+}
+
+TEST_F(SurfaceTest, SurfReference) {
+    VkvgSurface surf = vkvg_surface_create(NULL, 0, 0);
+    EXPECT_EQ(0, vkvg_surface_get_reference_count(surf));
+    vkvg_surface_reference(surf);
+
+    EXPECT_EQ(VKVG_STATUS_DEVICE_ERROR, vkvg_surface_status(surf));
+
+    surf = vkvg_surface_create(dev, 512, 512);
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_device_status(dev));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+    EXPECT_EQ(2, vkvg_device_get_reference_count(dev));
+    EXPECT_EQ(1, vkvg_surface_get_reference_count(surf));
+
+    vkvg_surface_reference(surf);
+
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+    EXPECT_EQ(2, vkvg_surface_get_reference_count(surf));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+
+    vkvg_surface_destroy(surf);
+
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+    EXPECT_EQ(1, vkvg_surface_get_reference_count(surf));
+    EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_surface_status(surf));
+
+    vkvg_surface_destroy(surf);
+    EXPECT_EQ(0, vkvg_surface_get_reference_count(surf));
+}
index 132aabac90b67bebab1a9ceef3729a6495be1076..1de905c4aca10a170e4f29b444dad4878a5170dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ * Copyright (c) 2018-2025 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
  *
  * 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
@@ -43,11 +43,13 @@ extern "C" {
  */
 
 /*! @file vkvg.h
- *     @brief The header of the VKVG library.
+ *     @brief Main header of the VKVG library.
  *
  *     This is the header file of the VKVG library.  It defines all its types and
  *     declares all its functions.
  *
+ *  To start drawing with vkvg, simply include this header.
+ *
  */
 /*! @defgroup surface Surface
  *     @brief Functions and types related to VKVG surface.
@@ -123,12 +125,12 @@ extern vkvg_wired_debug_mode vkvg_wired_debug;
 typedef enum {
     VKVG_STATUS_SUCCESS = 0,              /*!< no error occurred.*/
     VKVG_STATUS_NO_MEMORY,                /*!< out of memory*/
+    VKVG_STATUS_NULL_POINTER,             /*!< NULL pointer*/
     VKVG_STATUS_INVALID_RESTORE,          /*!< call to #vkvg_restore without matching call to #vkvg_save*/
     VKVG_STATUS_NO_CURRENT_POINT,         /*!< path command expecting a current point to be defined failed*/
     VKVG_STATUS_INVALID_MATRIX,           /*!< invalid matrix (not invertible)*/
     VKVG_STATUS_INVALID_STATUS,           /*!< */
     VKVG_STATUS_INVALID_INDEX,            /*!< */
-    VKVG_STATUS_NULL_POINTER,             /*!< NULL pointer*/
     VKVG_STATUS_WRITE_ERROR,              /*!< */
     VKVG_STATUS_PATTERN_TYPE_MISMATCH,    /*!< */
     VKVG_STATUS_PATTERN_INVALID_GRADIENT, /*!< occurs when stops count is zero */
@@ -136,11 +138,14 @@ typedef enum {
     VKVG_STATUS_FILE_NOT_FOUND,           /*!< */
     VKVG_STATUS_INVALID_DASH,             /*!< invalid value for a dash setting */
     VKVG_STATUS_INVALID_RECT,             /*!< rectangle with height or width equal to 0. */
-    VKVG_STATUS_TIMEOUT,         /*!< waiting for a vulkan operation to finish resulted in a fence timeout (5 seconds)*/
-    VKVG_STATUS_DEVICE_ERROR,    /*!< vkvg device initialization error */
-    VKVG_STATUS_INVALID_IMAGE,   /*!< */
-    VKVG_STATUS_INVALID_SURFACE, /*!< */
-    VKVG_STATUS_INVALID_FONT,    /*!< Unresolved font name*/
+    VKVG_STATUS_TIMEOUT,      /*!< waiting for a vulkan operation to finish resulted in a fence timeout (5 seconds)*/
+    VKVG_STATUS_DEVICE_ERROR, /*!< vkvg device initialization error */
+    VKVG_STATUS_INVALID_DEVICE_CREATE_INFO, /*!< vkvg device initialization error */
+    VKVG_STATUS_INVALID_IMAGE,              /*!< */
+    VKVG_STATUS_INVALID_SURFACE,            /*!< */
+    VKVG_STATUS_INVALID_FONT,               /*!< Unresolved font name*/
+    VKVG_STATUS_IN_CACHE, /*!< This is not an error, context is stored in cache, not usable until recovered for another
+                             context creation. */
     VKVG_STATUS_ENUM_MAX = 0x7FFFFFFF
 } vkvg_status_t;
 
@@ -329,6 +334,7 @@ typedef struct _vkvg_pattern_t *VkvgPattern;
  *
  * @ingroup device
  */
+#define VKVG_HAS_DBG_STATS /*!< If defined, #vkvg_device_get_stats and #vkvg_device_reset_stats are available.*/
 typedef struct {
     uint32_t sizePoints;   /**< maximum point array size                                       */
     uint32_t sizePathes;   /**< maximum path array size                                        */
@@ -339,7 +345,7 @@ typedef struct {
 } vkvg_debug_stats_t;
 
 vkvg_debug_stats_t vkvg_device_get_stats(VkvgDevice dev);
-vkvg_debug_stats_t vkvg_device_reset_stats(VkvgDevice dev);
+void               vkvg_device_reset_stats(VkvgDevice dev);
 #endif
 
 /**
@@ -554,20 +560,9 @@ typedef struct {
     VkDevice           vkdev;
     uint32_t           qFamIdx;
     uint32_t           qIndex;
+    bool               threadAware; /**< if true, mutex is created and guard device queue and caches access */
 } vkvg_device_create_info_t;
-/**
- * @brief Set device ready for multithreading.
- *
- * If thread aware mode is set to true,
- *
- * This method should be called only once on device creation. If this method is called while some surfaces or patterns
- * are in use, this could have unexpected results.
- *
- *
- * @param dev
- * @param thread_awayre
- */
-vkvg_public void vkvg_device_set_thread_aware(VkvgDevice dev, uint32_t thread_awayre);
+
 vkvg_public
     /**
      * @brief Set maximum cached context count.
@@ -590,6 +585,7 @@ vkvg_public
  * one of the following:
  * - VKVG_STATUS_INVALID_FORMAT: the combination of image format and tiling is not supported
  * - VKVG_STATUS_NULL_POINTER: vulkan function pointer fetching failed.
+ * - VKVG_STATUS_NO_MEMORY: either info parameter was null or memory allocation for device structure failed.
  *
  * @param samples The sample count that will be setup for the surfaces created by this device.
  * @param deferredResolve If true, the final simple sampled image of the surface will only be resolved on demand with a
@@ -630,7 +626,7 @@ vkvg_public VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info);
  * @param samples The sample count that will be setup for the surfaces created by this device.
 
  * @return The handle of the created vkvg device, or null if an error occured.
-
+ */
 
 /**
  * @brief Decrement the reference count of the device by 1. Release all its resources if count reaches 0.
@@ -755,6 +751,14 @@ vkvg_public VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *v
  */
 vkvg_public VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char *img, uint32_t width,
                                                         uint32_t height);
+/**
+ * @brief Get the current status of the surface.
+ *
+ * Query current status of surface. See @ref vkvg_status_t for more informations.
+ * @param surf a valid vkvg surface pointer. If null, VKVG_STATUS_NO_MEMORY is return;
+ * @return current state.
+ */
+vkvg_public vkvg_status_t vkvg_surface_status(VkvgSurface surf);
 /**
  * @brief Increment reference count on the surface by one.
  * @param The vkvg surface to increment the reference count for.
index 5b4376581c0d563a181c4bbb236e897dba77b10c..beb7078e7a1fea987ca96b8ac1abe347fdb56a29 100644 (file)
@@ -143,7 +143,7 @@ void main()
        }
 
        if (inFontUV.z >= 0.0)
-               c *= texture(fontMap, inFontUV).r;
+            c *= texture(fontMap, inFontUV).r;
 
 #ifdef VKVG_PREMULT_ALPHA
        c *= inOpacity;
index e047ba8d6ed4c5de1ed34e75864555d47d55219f..3fee0f4813d40c7ba05b02b96a4958af03e24bac 100644 (file)
@@ -19,8 +19,7 @@
  * 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
+#pragma once
 
 // cross platform os helpers
 #if defined(_WIN32) || defined(_WIN64)
@@ -53,5 +52,3 @@ void _linux_register_error_handler();
 #endif
 
 const char *getUserDir();
-
-#endif // CROSS_OS_H
index 9e4836544e5a9ebf095a0bf7f0a0e82081d227e2..9808c5eaa6ad76677b086da49b30a66be9503120 100644 (file)
@@ -1,5 +1,5 @@
 unsigned char shader_comp_spv[] = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -23,9 +23,9 @@ unsigned char shader_comp_spv[] = {
     0x00, 0x05, 0x00, 0x03, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00,
     0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x84, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
     0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00,
-    0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00,
-    0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x21, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47,
+    0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x97, 0x00, 0x00,
+    0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x97, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
     0x00, 0x04, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
     0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x02,
     0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -190,7 +190,7 @@ unsigned char shader_comp_spv[] = {
     0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
 unsigned int  shader_comp_spv_len = 3580;
 unsigned char shader2_comp_spv[]  = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -218,10 +218,10 @@ unsigned char shader2_comp_spv[]  = {
     0x61, 0x6d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x54, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00,
     0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x00, 0x00, 0x00, 0x05,
     0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00,
-    0x61, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
-    0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x61, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47,
-    0x00, 0x03, 0x00, 0x61, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6b, 0x00, 0x00, 0x00,
+    0x5e, 0x00, 0x00, 0x00, 0x62, 0x75, 0x66, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+    0x00, 0x1c, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x47, 0x00,
+    0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5e,
+    0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00,
     0x0b, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03,
     0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00,
     0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20,
@@ -246,14 +246,14 @@ unsigned char shader2_comp_spv[]  = {
     0x00, 0x4d, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4f, 0x00,
     0x00, 0x00, 0x6f, 0x12, 0x03, 0x3b, 0x17, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04,
     0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
-    0x19, 0x00, 0x09, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x19, 0x00, 0x09, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00,
-    0x04, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x60,
-    0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00,
-    0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x66, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-    0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x02, 0x00,
-    0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2c,
-    0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00,
+    0x04, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x5d,
+    0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x60, 0x00, 0x00, 0x00,
+    0x28, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x63, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+    0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x02, 0x00,
+    0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x2c,
+    0x00, 0x06, 0x00, 0x29, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
     0x35, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00,
     0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a,
@@ -292,45 +292,42 @@ unsigned char shader2_comp_spv[]  = {
     0x00, 0x00, 0x00, 0x39, 0x00, 0x09, 0x00, 0x06, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
     0x50, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00,
     0x00, 0x3e, 0x00, 0x03, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
-    0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5b,
-    0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
-    0x4a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
-    0x00, 0x50, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5b, 0x00,
-    0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5e,
-    0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00,
-    0x3d, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07,
-    0x00, 0x63, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x67, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x65,
-    0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
-    0x63, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01,
-    0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x37,
-    0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x0d, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03,
-    0x00, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00,
-    0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07,
-    0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00,
-    0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07,
-    0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
-    0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x83, 0x00,
-    0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0c,
-    0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
-    0x1a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
-    0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00,
-    0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06,
-    0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
-    0x21, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
-    0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06,
-    0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
-    0x1f, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01,
-    0x00};
-unsigned int  shader2_comp_spv_len = 2604;
+    0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x57, 0x00, 0x00, 0x00, 0x5b,
+    0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00,
+    0x3e, 0x00, 0x03, 0x00, 0x59, 0x00, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00,
+    0x00, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x29, 0x00, 0x00, 0x00, 0x61, 0x00,
+    0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x61,
+    0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00,
+    0x64, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00,
+    0x00, 0x66, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x63, 0x00, 0x04, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x65, 0x00,
+    0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00, 0x36, 0x00, 0x05, 0x00, 0x06,
+    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00,
+    0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+    0x00, 0x37, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x09, 0x00,
+    0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x37, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xf8,
+    0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+    0x07, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+    0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x83, 0x00,
+    0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0c,
+    0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+    0x15, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
+    0x00, 0x0c, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x28, 0x00,
+    0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x19,
+    0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+    0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
+    0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00,
+    0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x83, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1d,
+    0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00,
+    0x1d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00,
+    0x00, 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x88, 0x00,
+    0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0c,
+    0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+    0x22, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+    0x00, 0x31, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0xfe, 0x00,
+    0x02, 0x00, 0x24, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00};
+unsigned int  shader2_comp_spv_len = 2556;
 unsigned char vkvg_main_frag_spv[] = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -386,19 +383,19 @@ unsigned char vkvg_main_frag_spv[] = {
     0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00,
     0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x21,
     0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00,
-    0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
+    0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
+    0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
     0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47,
-    0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
-    0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
-    0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00,
-    0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48,
-    0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
-    0x47, 0x00, 0x03, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00,
-    0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x21, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03,
+    0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+    0x5a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x01, 0x00,
+    0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x02,
+    0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5a, 0x00, 0x00, 0x00,
+    0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00,
+    0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x22, 0x00,
+    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x7f, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x47, 0x00, 0x04, 0x00, 0x88, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03,
     0x00, 0x8f, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x8f, 0x01, 0x00, 0x00, 0x1e, 0x00,
     0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x94, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x96, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -834,7 +831,7 @@ unsigned char vkvg_main_frag_spv[] = {
     0x00, 0x95, 0x01, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
 unsigned int  vkvg_main_frag_spv_len = 9532;
 unsigned char vkvg_main_vert_spv[]   = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -874,27 +871,27 @@ unsigned char vkvg_main_vert_spv[]   = {
     0x00, 0x05, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x55, 0x56, 0x00, 0x00, 0x00, 0x05, 0x00,
     0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x55, 0x56, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x54,
     0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-    0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
-    0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48,
-    0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-    0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
-    0x00, 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48,
-    0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-    0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05,
-    0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x47,
-    0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
+    0x47, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03,
+    0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
+    0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00,
+    0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00,
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04,
+    0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00,
+    0x04, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00,
+    0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05, 0x00,
+    0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x05,
+    0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
     0x1e, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
     0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00,
     0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x2f,
-    0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00,
-    0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00,
-    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e,
-    0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
-    0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x3e, 0x00, 0x00, 0x00,
+    0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b,
+    0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+    0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x42, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x51, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13,
     0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
@@ -1031,7 +1028,7 @@ unsigned char vkvg_main_vert_spv[]   = {
     0x03, 0x00, 0x84, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
 unsigned int  vkvg_main_vert_spv_len   = 3704;
 unsigned char vkvg_main_lcd_frag_spv[] = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -1077,19 +1074,19 @@ unsigned char vkvg_main_lcd_frag_spv[] = {
     0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
     0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
     0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x47, 0x00,
-    0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4e,
-    0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
+    0x04, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x4e,
+    0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00,
     0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
     0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00,
-    0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
-    0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
-    0x00, 0x00, 0x02, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00,
-    0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47,
-    0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
-    0x5e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xdc, 0x00, 0x00,
-    0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x22, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x5c,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+    0x5c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05,
+    0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x48, 0x00,
+    0x05, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x47,
+    0x00, 0x04, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+    0x5e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xdc, 0x00, 0x00,
+    0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x21, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x47, 0x00, 0x04, 0x00, 0xee, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02,
     0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00,
@@ -1338,7 +1335,7 @@ unsigned char vkvg_main_lcd_frag_spv[] = {
     0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
 unsigned int  vkvg_main_lcd_frag_spv_len = 5784;
 unsigned char wired_frag_spv[]           = {
-    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c,
     0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
@@ -1371,18 +1368,18 @@ unsigned char wired_frag_spv[]           = {
     0x04, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x2b,
     0x00, 0x00, 0x00, 0x4e, 0x55, 0x4d, 0x5f, 0x53, 0x41, 0x4d, 0x50, 0x4c, 0x45, 0x53, 0x00, 0x47, 0x00, 0x04, 0x00,
     0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00,
-    0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01,
-    0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x22, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
     0x47, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04,
     0x00, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, 0x00,
-    0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00,
-    0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00,
-    0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a,
-    0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02,
+    0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00,
+    0x00, 0x00, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00,
+    0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23,
+    0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
     0x00, 0x47, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00,
     0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x24,
     0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
index 877afb8293e5f3bf43daf252bf067b26a1c426da..de3151d9b5512a21a623603dc3dd46b46fb7d250 100644 (file)
@@ -51,10 +51,7 @@ void _init_ctx(VkvgContext ctx) {
 
     vkvg_surface_reference(ctx->pSurf);
 
-    if (ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT)
-        ctx->renderPassBeginInfo.clearValueCount = 2;
-    else
-        ctx->renderPassBeginInfo.clearValueCount = 3;
+    ctx->renderPassBeginInfo.clearValueCount = ctx->dev->samples == VK_SAMPLE_COUNT_1_BIT ? 2 : 3;
 
     ctx->selectedCharSize    = 10 << 6;
     ctx->currentFont         = NULL;
@@ -70,38 +67,37 @@ void _init_ctx(VkvgContext ctx) {
 }
 
 VkvgContext vkvg_create(VkvgSurface surf) {
+    LOG(VKVG_LOG_INFO, "CREATE Context\n");
+    if (vkvg_surface_status(surf)) {
+        LOG(VKVG_LOG_ERR, "CREATE Context failed, invalid surface\n");
+        return (VkvgContext)&_vkvg_status_invalid_surface;
+    }
     VkvgDevice  dev = surf->dev;
+    if (vkvg_device_status(dev)) {
+        LOG(VKVG_LOG_ERR, "CREATE Context failed, invalid device\n");
+        return (VkvgContext)&_vkvg_status_device_error;
+    }
     VkvgContext ctx = NULL;
 
     if (_device_try_get_cached_context(dev, &ctx)) {
         ctx->pSurf = surf;
-
-        if (!surf || surf->status) {
-            ctx->status = VKVG_STATUS_INVALID_SURFACE;
-            return ctx;
-        }
-
+        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
-        ctx->status = VKVG_STATUS_SUCCESS;
+        ctx->cmd = ctx->cmdBuffers[0]; // current recording buffer
         return ctx;
     }
     ctx = (vkvg_context *)calloc(1, sizeof(vkvg_context));
 
-    LOG(VKVG_LOG_INFO, "CREATE Context: ctx = %p; surf = %p\n", ctx, surf);
-
-    if (!ctx)
-        return (VkvgContext)&_no_mem_status;
+    if (!ctx) {
+        LOG(VKVG_LOG_ERR, "CREATE context failed, no memory\n");
+        return (VkvgContext)&_vkvg_status_no_memory;
+    }
 
+    LOG(VKVG_LOG_INFO, "CREATE Context: ctx = %p; surf = %p\n", ctx, surf);
     ctx->pSurf = surf;
 
-    if (!surf || surf->status) {
-        ctx->status = VKVG_STATUS_INVALID_SURFACE;
-        return ctx;
-    }
-
     ctx->sizePoints   = VKVG_PTS_SIZE;
     ctx->sizeVertices = ctx->sizeVBO = VKVG_VBO_SIZE;
     ctx->sizeIndices = ctx->sizeIBO = VKVG_IBO_SIZE;
@@ -110,15 +106,12 @@ VkvgContext vkvg_create(VkvgSurface surf) {
 
     ctx->dev = surf->dev;
 
-    _init_ctx(ctx);
-
     ctx->points      = (vec2 *)malloc(VKVG_VBO_SIZE * sizeof(vec2));
     ctx->pathes      = (uint32_t *)malloc(VKVG_PATHES_SIZE * sizeof(uint32_t));
     ctx->vertexCache = (Vertex *)malloc(ctx->sizeVertices * sizeof(Vertex));
     ctx->indexCache  = (VKVG_IBO_INDEX_TYPE *)malloc(ctx->sizeIndices * sizeof(VKVG_IBO_INDEX_TYPE));
 
     if (!ctx->points || !ctx->pathes || !ctx->vertexCache || !ctx->indexCache) {
-        dev->status = VKVG_STATUS_NO_MEMORY;
         if (ctx->points)
             free(ctx->points);
         if (ctx->pathes)
@@ -127,15 +120,18 @@ VkvgContext vkvg_create(VkvgSurface surf) {
             free(ctx->vertexCache);
         if (ctx->indexCache)
             free(ctx->indexCache);
-        return NULL;
+        LOG(VKVG_LOG_ERR, "CREATE context failed, no memory\n");
+        return (VkvgContext)&_vkvg_status_no_memory;
     }
 
+    _init_ctx(ctx);
+
+    VkhDevice vkhd = (VkhDevice)&dev->vkDev;
     // for context to be thread safe, command pool and descriptor pool have to be created in the thread of the context.
-    ctx->cmdPool =
-        vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+    ctx->cmdPool = vkh_cmd_pool_create(vkhd, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
 
 #ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
-    ctx->flushFence = vkh_fence_create_signaled((VkhDevice)ctx->dev);
+    ctx->flushFence = vkh_fence_create_signaled((VkhDevice)&ctx->dev->vkDev);
 #endif
 
     _create_vertices_buff(ctx);
@@ -159,32 +155,26 @@ VkvgContext vkvg_create(VkvgSurface surf) {
         ctx->sizeIBO);
 
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)ctx->cmdPool, "CTX Cmd Pool");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[0],
-                               "CTX Cmd Buff A");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[1],
-                               "CTX Cmd Buff B");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)ctx->cmdPool, "CTX Cmd Pool");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[0], "CTX Cmd Buff A");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)ctx->cmdBuffers[1], "CTX Cmd Buff B");
 #ifndef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_FENCE, (uint64_t)ctx->flushFence, "CTX Flush Fence");
 #endif
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool,
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_POOL, (uint64_t)ctx->descriptorPool,
                                "CTX Descriptor Pool");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc,
-                               "CTX DescSet SOURCE");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont,
-                               "CTX DescSet FONT");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsGrad,
-                               "CTX DescSet GRADIENT");
-
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->indices.buffer, "CTX Index Buff");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->vertices.buffer,
-                               "CTX Vertex Buff");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsSrc, "CTX DescSet SOURCE");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsFont, "CTX DescSet FONT");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)ctx->dsGrad, "CTX DescSet GRADIENT");
+
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->indices.buffer, "CTX Index Buff");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_BUFFER, (uint64_t)ctx->vertices.buffer, "CTX Vertex Buff");
 #endif
 
     return ctx;
 }
 void vkvg_flush(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     _flush_cmd_buff(ctx);
     _wait_ctx_flush_end(ctx);
@@ -250,7 +240,7 @@ void _clear_context(VkvgContext ctx) {
 }
 
 void vkvg_destroy(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     ctx->references--;
@@ -300,13 +290,14 @@ void vkvg_destroy(VkvgContext ctx) {
 
     if (!ctx->status && ctx->dev->cachedContextCount < VKVG_MAX_CACHED_CONTEXT_COUNT) {
         _device_store_context(ctx);
+        ctx->status = VKVG_STATUS_IN_CACHE;
         return;
     }
 
     _release_context_ressources(ctx);
 }
 void vkvg_set_opacity(VkvgContext ctx, float opacity) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     if (EQUF(ctx->pushConsts.opacity, opacity))
@@ -317,23 +308,23 @@ void vkvg_set_opacity(VkvgContext ctx, float opacity) {
     ctx->pushCstDirty       = true;
 }
 float vkvg_get_opacity(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return 0;
     return ctx->pushConsts.opacity;
 }
-vkvg_status_t vkvg_status(VkvgContext ctx) { return ctx->status; }
+vkvg_status_t vkvg_status(VkvgContext ctx) { return !ctx ? VKVG_STATUS_NULL_POINTER : ctx->status; }
 VkvgContext   vkvg_reference(VkvgContext ctx) {
     if (!ctx->status)
         ctx->references++;
     return ctx;
 }
 uint32_t vkvg_get_reference_count(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return 0;
     return ctx->references;
 }
 void vkvg_new_sub_path(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_NEW_SUB_PATH);
@@ -342,7 +333,7 @@ void vkvg_new_sub_path(VkvgContext ctx) {
     _finish_path(ctx);
 }
 void vkvg_new_path(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: new_path:\n");
@@ -351,7 +342,7 @@ void vkvg_new_path(VkvgContext ctx) {
     RECORD(ctx, VKVG_CMD_NEW_PATH);
 }
 void vkvg_close_path(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_CLOSE_PATH);
@@ -375,7 +366,7 @@ void vkvg_close_path(VkvgContext ctx) {
     _finish_path(ctx);
 }
 void vkvg_rel_line_to(VkvgContext ctx, float dx, float dy) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_REL_LINE_TO, dx, dy);
@@ -387,7 +378,7 @@ void vkvg_rel_line_to(VkvgContext ctx, float dx, float dy) {
     _line_to(ctx, cp.x + dx, cp.y + dy);
 }
 void vkvg_line_to(VkvgContext ctx, float x, float y) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_LINE_TO, x, y);
@@ -395,7 +386,7 @@ void vkvg_line_to(VkvgContext ctx, float x, float y) {
     _line_to(ctx, x, y);
 }
 void vkvg_arc(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_ARC, xc, yc, radius, a1, a2);
@@ -451,7 +442,7 @@ void vkvg_arc(VkvgContext ctx, float xc, float yc, float radius, float a1, float
     _set_curve_end(ctx);
 }
 void vkvg_arc_negative(VkvgContext ctx, float xc, float yc, float radius, float a1, float a2) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_ARC_NEG, xc, yc, radius, a1, a2);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: %f,%f %f %f %f\n", xc, yc, radius, a1, a2);
@@ -505,7 +496,7 @@ void vkvg_arc_negative(VkvgContext ctx, float xc, float yc, float radius, float
     _set_curve_end(ctx);
 }
 void vkvg_rel_move_to(VkvgContext ctx, float x, float y) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_REL_MOVE_TO, x, y);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_mote_to: %f, %f\n", x, y);
@@ -516,7 +507,7 @@ void vkvg_rel_move_to(VkvgContext ctx, float x, float y) {
     _add_point(ctx, cp.x + x, cp.y + y);
 }
 void vkvg_move_to(VkvgContext ctx, float x, float y) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_MOVE_TO, x, y);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: move_to: %f,%f\n", x, y);
@@ -524,7 +515,7 @@ void vkvg_move_to(VkvgContext ctx, float x, float y) {
     _add_point(ctx, x, y);
 }
 bool vkvg_has_current_point(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return false;
     return !_current_path_is_empty(ctx);
 }
@@ -575,14 +566,14 @@ void         _quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float
                       y2 + (y1 - y2) * quadraticFact, x2, y2);
 }
 void vkvg_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_QUADRATIC_TO, x1, y1, x2, y2);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
     _quadratic_to(ctx, x1, y1, x2, y2);
 }
 void vkvg_rel_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float y2) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_REL_QUADRATIC_TO, x1, y1, x2, y2);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: rel_quadratic_to: %f, %f, %f, %f\n", x1, y1, x2, y2);
@@ -590,14 +581,14 @@ void vkvg_rel_quadratic_to(VkvgContext ctx, float x1, float y1, float x2, float
     _quadratic_to(ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2);
 }
 void vkvg_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_CURVE_TO, x1, y1, x2, y2, x3, y3);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: curve_to %f,%f %f,%f %f,%f:\n", x1, y1, x2, y2, x3, y3);
     _curve_to(ctx, x1, y1, x2, y2, x3, y3);
 }
 void vkvg_rel_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2, float x3, float y3) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     if (_current_path_is_empty(ctx)) {
         ctx->status = VKVG_STATUS_NO_CURRENT_POINT;
@@ -609,7 +600,7 @@ void vkvg_rel_curve_to(VkvgContext ctx, float x1, float y1, float x2, float y2,
     _curve_to(ctx, cp.x + x1, cp.y + y1, cp.x + x2, cp.y + y2, cp.x + x3, cp.y + y3);
 }
 void vkvg_fill_rectangle(VkvgContext ctx, float x, float y, float w, float h) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: fill_rectangle:\n");
     _vao_add_rectangle(ctx, x, y, w, h);
@@ -617,7 +608,7 @@ void vkvg_fill_rectangle(VkvgContext ctx, float x, float y, float w, float h) {
 }
 
 vkvg_status_t vkvg_rectangle(VkvgContext ctx, float x, float y, float w, float h) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return ctx->status;
     RECORD2(ctx, VKVG_CMD_RECTANGLE, x, y, w, h);
     LOG(VKVG_LOG_INFO_CMD, "\tCMD: rectangle: %f,%f,%f,%f\n", x, y, w, h);
@@ -637,7 +628,7 @@ vkvg_status_t vkvg_rectangle(VkvgContext ctx, float x, float y, float w, float h
     return VKVG_STATUS_SUCCESS;
 }
 vkvg_status_t vkvg_rounded_rectangle(VkvgContext ctx, float x, float y, float w, float h, float radius) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return ctx->status;
     LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle:\n");
     _finish_path(ctx);
@@ -662,7 +653,7 @@ vkvg_status_t vkvg_rounded_rectangle(VkvgContext ctx, float x, float y, float w,
     return VKVG_STATUS_SUCCESS;
 }
 void vkvg_rounded_rectangle2(VkvgContext ctx, float x, float y, float w, float h, float rx, float ry) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     LOG(VKVG_LOG_INFO_CMD, "CMD: rounded_rectangle2:\n");
     vkvg_move_to(ctx, x + rx, y);
@@ -681,7 +672,7 @@ void vkvg_rounded_rectangle2(VkvgContext ctx, float x, float y, float w, float h
     vkvg_close_path(ctx);
 }
 void vkvg_path_extents(VkvgContext ctx, float *x1, float *y1, float *x2, float *y2) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     _finish_path(ctx);
@@ -716,7 +707,7 @@ void _reset_clip(VkvgContext ctx) {
 }
 
 void vkvg_reset_clip(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_RESET_CLIP);
@@ -731,7 +722,7 @@ void vkvg_reset_clip(VkvgContext ctx) {
     _reset_clip(ctx);
 }
 void vkvg_clear(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_CLEAR);
@@ -947,47 +938,47 @@ void _stroke_preserve(VkvgContext ctx) {
 }
 
 void vkvg_clip(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_CLIP);
     _clip_preserve(ctx);
     _clear_path(ctx);
 }
 void vkvg_stroke(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_STROKE);
     _stroke_preserve(ctx);
     _clear_path(ctx);
 }
 void vkvg_fill(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_FILL);
     _fill_preserve(ctx);
     _clear_path(ctx);
 }
 void vkvg_clip_preserve(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_CLIP_PRESERVE);
     _clip_preserve(ctx);
 }
 void vkvg_fill_preserve(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_FILL_PRESERVE);
     _fill_preserve(ctx);
 }
 void vkvg_stroke_preserve(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_STROKE_PRESERVE);
     _stroke_preserve(ctx);
 }
 
 void vkvg_paint(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_PAINT);
     _finish_path(ctx);
@@ -1001,21 +992,21 @@ void vkvg_paint(VkvgContext ctx) {
     _draw_full_screen_quad(ctx, NULL);
 }
 void vkvg_set_source_color(VkvgContext ctx, uint32_t c) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_SOURCE_COLOR, c);
     ctx->curColor = c;
     _update_cur_pattern(ctx, NULL);
 }
 void vkvg_set_source_rgb(VkvgContext ctx, float r, float g, float b) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_SOURCE_RGB, r, g, b);
     ctx->curColor = CreateRgbaf(r, g, b, 1);
     _update_cur_pattern(ctx, NULL);
 }
 void vkvg_set_source_rgba(VkvgContext ctx, float r, float g, float b, float a) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_SOURCE_RGBA, r, g, b, a);
     ctx->curColor = CreateRgbaf(r, g, b, a);
@@ -1038,31 +1029,31 @@ void vkvg_set_source(VkvgContext ctx, VkvgPattern pat) {
     vkvg_pattern_reference(pat);
 }
 void vkvg_set_line_width(VkvgContext ctx, float width) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, width);
     ctx->lineWidth = width;
 }
 void vkvg_set_miter_limit(VkvgContext ctx, float limit) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_LINE_WIDTH, limit);
     ctx->miterLimit = limit;
 }
 void vkvg_set_line_cap(VkvgContext ctx, vkvg_line_cap_t cap) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_LINE_CAP, cap);
     ctx->lineCap = cap;
 }
 void vkvg_set_line_join(VkvgContext ctx, vkvg_line_join_t join) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_LINE_JOIN, join);
     ctx->lineJoin = join;
 }
 void vkvg_set_operator(VkvgContext ctx, vkvg_operator_t op) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_OPERATOR, op);
     if (op == ctx->curOperator)
@@ -1077,7 +1068,7 @@ void vkvg_set_operator(VkvgContext ctx, vkvg_operator_t op) {
         _bind_draw_pipeline(ctx);
 }
 void vkvg_set_fill_rule(VkvgContext ctx, vkvg_fill_rule_t fr) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 #ifndef __APPLE__
     RECORD(ctx, VKVG_CMD_SET_FILL_RULE, fr);
@@ -1085,17 +1076,17 @@ void vkvg_set_fill_rule(VkvgContext ctx, vkvg_fill_rule_t fr) {
 #endif
 }
 vkvg_fill_rule_t vkvg_get_fill_rule(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return VKVG_FILL_RULE_NON_ZERO;
     return ctx->curFillRule;
 }
 float vkvg_get_line_width(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return 0;
     return ctx->lineWidth;
 }
 void vkvg_set_dash(VkvgContext ctx, const float *dashes, uint32_t num_dashes, float offset) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     if (ctx->dashCount > 0)
         free(ctx->dashes);
@@ -1108,7 +1099,7 @@ void vkvg_set_dash(VkvgContext ctx, const float *dashes, uint32_t num_dashes, fl
     memcpy(ctx->dashes, dashes, sizeof(float) * ctx->dashCount);
 }
 void vkvg_get_dash(VkvgContext ctx, const float *dashes, uint32_t *num_dashes, float *offset) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     *num_dashes = ctx->dashCount;
     *offset     = ctx->dashOffset;
@@ -1118,35 +1109,35 @@ void vkvg_get_dash(VkvgContext ctx, const float *dashes, uint32_t *num_dashes, f
 }
 
 vkvg_line_cap_t vkvg_get_line_cap(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return (vkvg_line_cap_t)0;
     return ctx->lineCap;
 }
 vkvg_line_join_t vkvg_get_line_join(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return (vkvg_line_join_t)0;
     return ctx->lineJoin;
 }
 vkvg_operator_t vkvg_get_operator(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return (vkvg_operator_t)0;
     return ctx->curOperator;
 }
 VkvgPattern vkvg_get_source(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return NULL;
     vkvg_pattern_reference(ctx->pattern);
     return ctx->pattern;
 }
 
 void vkvg_select_font_face(VkvgContext ctx, const char *name) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_FONT_FACE, name);
     _select_font_face(ctx, name);
 }
 void vkvg_load_font_from_path(VkvgContext ctx, const char *path, const char *name) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
     _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, path, name);
@@ -1157,7 +1148,7 @@ void vkvg_load_font_from_path(VkvgContext ctx, const char *path, const char *nam
     _select_font_face(ctx, name);
 }
 void vkvg_load_font_from_memory(VkvgContext ctx, unsigned char *fontBuffer, long fontBufferByteSize, const char *name) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     // RECORD(ctx, VKVG_CMD_SET_FONT_PATH, name);
     _vkvg_font_identity_t *fid = _font_cache_add_font_identity(ctx, NULL, name);
@@ -1167,7 +1158,7 @@ void vkvg_load_font_from_memory(VkvgContext ctx, unsigned char *fontBuffer, long
     _select_font_face(ctx, name);
 }
 void vkvg_set_font_size(VkvgContext ctx, uint32_t size) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_FONT_SIZE, size);
 #ifdef VKVG_USE_FREETYPE
@@ -1185,7 +1176,7 @@ void vkvg_set_font_size(VkvgContext ctx, uint32_t size) {
 void vkvg_set_text_direction(vkvg_context *ctx, vkvg_direction_t direction) {}
 
 void vkvg_show_text(VkvgContext ctx, const char *text) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SHOW_TEXT, text);
     LOG(VKVG_LOG_INFO_CMD, "CMD: show_text:\n");
@@ -1195,14 +1186,14 @@ void vkvg_show_text(VkvgContext ctx, const char *text) {
 }
 
 VkvgText vkvg_text_run_create(VkvgContext ctx, const char *text) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return NULL;
     VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
     _font_cache_create_text_run(ctx, text, -1, tr);
     return tr;
 }
 VkvgText vkvg_text_run_create_with_length(VkvgContext ctx, const char *text, uint32_t length) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return NULL;
     VkvgText tr = (vkvg_text_run_t *)calloc(1, sizeof(vkvg_text_run_t));
     _font_cache_create_text_run(ctx, text, length, tr);
@@ -1225,25 +1216,25 @@ void vkvg_text_run_destroy(VkvgText textRun) {
     free(textRun);
 }
 void vkvg_show_text_run(VkvgContext ctx, VkvgText textRun) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     _font_cache_show_text_run(ctx, textRun);
 }
 void vkvg_text_run_get_extents(VkvgText textRun, vkvg_text_extents_t *extents) { *extents = textRun->extents; }
 
 void vkvg_text_extents(VkvgContext ctx, const char *text, vkvg_text_extents_t *extents) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     _font_cache_text_extents(ctx, text, -1, extents);
 }
 void vkvg_font_extents(VkvgContext ctx, vkvg_font_extents_t *extents) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     _font_cache_font_extents(ctx, extents);
 }
 
 void vkvg_save(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SAVE);
     LOG(VKVG_LOG_INFO, "SAVE CONTEXT: ctx = %p\n", ctx);
@@ -1275,7 +1266,7 @@ void vkvg_save(VkvgContext ctx) {
             }
             ctx->savedStencils  = savedStencilsPtr;
             VkhImage savStencil = vkh_image_ms_create(
-                (VkhDevice)dev, dev->stencilFormat, dev->samples, ctx->pSurf->width, ctx->pSurf->height,
+                (VkhDevice)&ctx->dev->vkDev, dev->stencilFormat, dev->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;
 
@@ -1368,7 +1359,7 @@ void vkvg_save(VkvgContext ctx) {
     ctx->pSavedCtxs = sav;
 }
 void vkvg_restore(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
 
     RECORD(ctx, VKVG_CMD_RESTORE);
@@ -1506,7 +1497,7 @@ void vkvg_restore(VkvgContext ctx) {
 }
 
 void vkvg_translate(VkvgContext ctx, float dx, float dy) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_TRANSLATE, dx, dy);
     LOG(VKVG_LOG_INFO_CMD, "CMD: translate: %f, %f\n", dx, dy);
@@ -1515,7 +1506,7 @@ void vkvg_translate(VkvgContext ctx, float dx, float dy) {
     _set_mat_inv_and_vkCmdPush(ctx);
 }
 void vkvg_scale(VkvgContext ctx, float sx, float sy) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SCALE, sx, sy);
     LOG(VKVG_LOG_INFO_CMD, "CMD: scale: %f, %f\n", sx, sy);
@@ -1524,7 +1515,7 @@ void vkvg_scale(VkvgContext ctx, float sx, float sy) {
     _set_mat_inv_and_vkCmdPush(ctx);
 }
 void vkvg_rotate(VkvgContext ctx, float radians) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_ROTATE, radians);
     LOG(VKVG_LOG_INFO_CMD, "CMD: rotate: %f\n", radians);
@@ -1533,7 +1524,7 @@ void vkvg_rotate(VkvgContext ctx, float radians) {
     _set_mat_inv_and_vkCmdPush(ctx);
 }
 void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t *matrix) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_TRANSFORM, matrix);
     LOG(VKVG_LOG_INFO_CMD, "CMD: transform: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy,
@@ -1545,7 +1536,7 @@ void vkvg_transform(VkvgContext ctx, const vkvg_matrix_t *matrix) {
     _set_mat_inv_and_vkCmdPush(ctx);
 }
 void vkvg_identity_matrix(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_IDENTITY_MATRIX);
     LOG(VKVG_LOG_INFO_CMD, "CMD: identity_matrix:\n");
@@ -1555,7 +1546,7 @@ void vkvg_identity_matrix(VkvgContext ctx) {
     _set_mat_inv_and_vkCmdPush(ctx);
 }
 void vkvg_set_matrix(VkvgContext ctx, const vkvg_matrix_t *matrix) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_SET_MATRIX, matrix);
     LOG(VKVG_LOG_INFO_CMD, "CMD: set_matrix: %f, %f, %f, %f, %f, %f\n", matrix->xx, matrix->yx, matrix->xy, matrix->yy,
@@ -1568,7 +1559,7 @@ void vkvg_get_matrix(VkvgContext ctx, vkvg_matrix_t *const matrix) { *matrix = c
 
 void vkvg_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry,
                           float phi) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
     LOG(VKVG_LOG_INFO_CMD,
@@ -1580,7 +1571,7 @@ void vkvg_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc, bo
 }
 void vkvg_rel_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc, bool sweepFlag, float rx, float ry,
                               float phi) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     RECORD(ctx, VKVG_CMD_REL_ELLIPTICAL_ARC_TO, x2, y2, rx, ry, phi, largeArc, sweepFlag);
     LOG(VKVG_LOG_INFO_CMD,
@@ -1593,7 +1584,7 @@ void vkvg_rel_elliptic_arc_to(VkvgContext ctx, float x2, float y2, bool largeArc
 }
 
 void vkvg_ellipse(VkvgContext ctx, float radiusX, float radiusY, float x, float y, float rotationAngle) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return;
     LOG(VKVG_LOG_INFO_CMD, "CMD: ellipse:\n");
 
@@ -1629,7 +1620,7 @@ void vkvg_ellipse(VkvgContext ctx, float radiusX, float radiusY, float x, float
 }
 
 VkvgSurface vkvg_get_target(VkvgContext ctx) {
-    if (ctx->status)
+    if (vkvg_status(ctx))
         return NULL;
     return ctx->pSurf;
 }
@@ -1638,8 +1629,8 @@ const char *vkvg_status_to_string(vkvg_status_t status) {
     switch (status) {
     case VKVG_STATUS_SUCCESS:
         return "no error has occurred";
-    case VKVG_STATUS_NO_MEMORY:
-        return "out of memory";
+    /*case VKVG_STATUS_NO_MEMORY:
+        return "out of memory";*/
     case VKVG_STATUS_INVALID_RESTORE:
         return "vkvg_restore() without matching vkvg_save()";
     case VKVG_STATUS_NO_CURRENT_POINT:
index ce689474970424de2259579048dbe96a5139d40d..7b549cd66fbb7504ffc65b36259b1a77194bc9bd 100644 (file)
@@ -251,13 +251,13 @@ float _get_arc_step(VkvgContext ctx, float radius) {
     return fminf(M_PIF / 3.f, M_PIF / (r * 0.4f));
 }
 void _create_gradient_buff(VkvgContext ctx) {
-    vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+    vkh_buffer_init((VkhDevice)&ctx->dev->vkDev, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
                     sizeof(vkvg_gradient_t), &ctx->uboGrad, true);
 }
 void _create_vertices_buff(VkvgContext ctx) {
-    vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+    vkh_buffer_init((VkhDevice)&ctx->dev->vkDev, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
                     ctx->sizeVBO * sizeof(Vertex), &ctx->vertices, true);
-    vkh_buffer_init((VkhDevice)ctx->dev, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
+    vkh_buffer_init((VkhDevice)&ctx->dev->vkDev, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU,
                     ctx->sizeIBO * sizeof(VKVG_IBO_INDEX_TYPE), &ctx->indices, true);
 }
 void _resize_vbo(VkvgContext ctx, uint32_t new_size) {
@@ -395,9 +395,10 @@ void _ensure_renderpass_is_started(VkvgContext ctx) {
         _update_push_constants(ctx);
 }
 void _create_cmd_buff(VkvgContext ctx) {
-    vkh_cmd_buffs_create((VkhDevice)ctx->dev, ctx->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2, ctx->cmdBuffers);
+    vkh_cmd_buffs_create((VkhDevice)&ctx->dev->vkDev, ctx->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 2,
+                         ctx->cmdBuffers);
 #if defined(DEBUG) && defined(ENABLE_VALIDATION)
-    vkh_device_set_object_name((VkhDevice)ctx->pSurf->dev, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+    vkh_device_set_object_name((VkhDevice)&ctx->pSurf->dev->vkDev, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
                                (uint64_t)ctx->cmd, "vkvgCtxCmd");
 #endif
 }
@@ -406,7 +407,7 @@ void _clear_attachment(VkvgContext ctx) {}
 bool _wait_ctx_flush_end(VkvgContext ctx) {
     LOG(VKVG_LOG_INFO, "CTX: _wait_flush_fence\n");
 #ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
-    if (vkh_timeline_wait((VkhDevice)ctx->dev, ctx->pSurf->timeline, ctx->timelineStep) == VK_SUCCESS)
+    if (vkh_timeline_wait((VkhDevice)&ctx->dev->vkDev, ctx->pSurf->timeline, ctx->timelineStep) == VK_SUCCESS)
         return true;
 #else
     if (WaitForFences(ctx->dev->vkDev, 1, &ctx->flushFence, VK_TRUE, VKVG_FENCE_TIMEOUT) == VK_SUCCESS)
@@ -426,7 +427,7 @@ bool _wait_and_submit_cmd(VkvgContext ctx) {
 #ifdef VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
     VkvgSurface surf = ctx->pSurf;
     VkvgDevice  dev  = surf->dev;
-    // vkh_timeline_wait ((VkhDevice)dev, surf->timeline, ct->timelineStep);
+    // vkh_timeline_wait ((VkhDevice)&dev->vkDev, surf->timeline, ct->timelineStep);
     if (ctx->pattern && ctx->pattern->type == VKVG_PATTERN_TYPE_SURFACE) {
         // add source surface timeline sync.
         VkvgSurface source = (VkvgSurface)ctx->pattern->data;
@@ -755,11 +756,19 @@ void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat) {
 
         _update_descriptor_set(ctx, surf->img, ctx->dsSrc);
 
+        ctx->pushConsts.source.width  = (float)surf->width;
+        ctx->pushConsts.source.height = (float)surf->height;
+
+        vkvg_matrix_t mat;
         if (pat->hasMatrix) {
+            vkvg_pattern_get_matrix(pat, &mat);
+            // if (vkvg_matrix_invert(&mat) != VKVG_STATUS_SUCCESS)
+            //     mat = VKVG_IDENTITY_MATRIX;
+            // vkvg_matrix_transform_point(&mat, &ctx->pushConsts.source.x, &ctx->pushConsts.source.y);
+            // vkvg_matrix_transform_distance(&mat, &ctx->pushConsts.source.width, &ctx->pushConsts.source.height);
+            vkvg_matrix_multiply(&ctx->pushConsts.matInv, &ctx->pushConsts.matInv, &mat);
         }
 
-        ctx->pushConsts.source.width  = (float)surf->width;
-        ctx->pushConsts.source.height = (float)surf->height;
         break;
     }
     case VKVG_PATTERN_TYPE_LINEAR:
@@ -784,15 +793,15 @@ void _update_cur_pattern(VkvgContext ctx, VkvgPattern pat) {
             ctx->status = VKVG_STATUS_PATTERN_INVALID_GRADIENT;
             return;
         }
+
         vkvg_matrix_t mat;
         if (pat->hasMatrix) {
             vkvg_pattern_get_matrix(pat, &mat);
             if (vkvg_matrix_invert(&mat) != VKVG_STATUS_SUCCESS)
                 mat = VKVG_IDENTITY_MATRIX;
+            vkvg_matrix_transform_point(&mat, &grad.cp[0].x, &grad.cp[0].y);
         }
 
-        if (pat->hasMatrix)
-            vkvg_matrix_transform_point(&mat, &grad.cp[0].x, &grad.cp[0].y);
         vkvg_matrix_transform_point(&ctx->pushConsts.mat, &grad.cp[0].x, &grad.cp[0].y);
         if (pat->type == VKVG_PATTERN_TYPE_LINEAR) {
             if (pat->hasMatrix)
index ad54fea3d0f7cfce003a0653e5199b7ff962efad..d45a28e38b60b80e630935c0bac2ced6ea468abe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2022 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+ * Copyright (c) 2018-2025 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
  *
  * 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
@@ -71,6 +71,8 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t *info) {
     if (dev->status != VKVG_STATUS_SUCCESS)
         return;
 
+    VkhDevice vkhd = (VkhDevice)&dev->vkDev;
+
     if (!_device_init_function_pointers(dev)) {
         dev->status = VKVG_STATUS_NULL_POINTER;
         return;
@@ -79,7 +81,7 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t *info) {
     VkhPhyInfo phyInfos = vkh_phyinfo_create(dev->phy, NULL);
 
     dev->phyMemProps = phyInfos->memProps;
-    dev->gQueue      = vkh_queue_create((VkhDevice)dev, info->qFamIdx, info->qIndex);
+    dev->gQueue      = vkh_queue_create(vkhd, info->qFamIdx, info->qIndex);
     // mtx_init (&dev->gQMutex, mtx_plain);
 
     vkh_phyinfo_destroy(phyInfos);
@@ -89,10 +91,9 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t *info) {
     vmaCreateAllocator(&allocatorInfo, (VmaAllocator *)&dev->allocator);
 #endif
 
-    dev->cmdPool =
-        vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
-    dev->cmd   = vkh_cmd_buff_create((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
-    dev->fence = vkh_fence_create_signaled((VkhDevice)dev);
+    dev->cmdPool = vkh_cmd_pool_create(vkhd, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
+    dev->cmd     = vkh_cmd_buff_create(vkhd, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+    dev->fence   = vkh_fence_create_signaled(vkhd);
 
     _device_create_pipeline_cache(dev);
     _fonts_cache_create(dev);
@@ -120,38 +121,31 @@ void _device_init(VkvgDevice dev, const vkvg_device_create_info_t *info) {
     _linux_register_error_handler();
 #endif
 #ifdef VKVG_DBG_UTILS
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)dev->cmdPool, "Device Cmd Pool");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)dev->cmd, "Device Cmd Buff");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->fence, "Device Fence");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass,
-                               "RP load img/stencil");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearStencil,
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_POOL, (uint64_t)dev->cmdPool, "Device Cmd Pool");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)dev->cmd, "Device Cmd Buff");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_FENCE, (uint64_t)dev->fence, "Device Fence");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass, "RP load img/stencil");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearStencil,
                                "RP clear stencil");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll,
-                               "RP clear all");
-
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslSrc,
-                               "DSLayout SOURCE");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslFont,
-                               "DSLayout FONT");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslGrad,
-                               "DSLayout GRADIENT");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE_LAYOUT, (uint64_t)dev->pipelineLayout,
-                               "PLLayout dev");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_RENDER_PASS, (uint64_t)dev->renderPass_ClearAll, "RP clear all");
+
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t)dev->dslSrc, "DSLayout SOURCE");
+    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");
 
 #ifndef __APPLE__
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelinePolyFill,
-                               "PL Poly fill");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelinePolyFill, "PL Poly fill");
 #endif
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelineClipping, "PL Clipping");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_OVER, "PL draw Over");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_SUB, "PL draw Substract");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_CLEAR, "PL draw Clear");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipelineClipping, "PL Clipping");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_OVER, "PL draw Over");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_SUB, "PL draw Substract");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_PIPELINE, (uint64_t)dev->pipe_CLEAR, "PL draw Clear");
 
     vkh_image_set_name(dev->emptyImg, "empty IMG");
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(dev->emptyImg),
+    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((VkhDevice)dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(dev->emptyImg),
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(dev->emptyImg),
                                "empty IMG SAMPLER");
 #endif
 #endif
@@ -286,14 +280,25 @@ const void *vkvg_get_device_requirements(VkPhysicalDeviceFeatures *pEnabledFeatu
 
 VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info) {
     LOG(VKVG_LOG_INFO, "CREATE Device\n");
+    if (!info) {
+        LOG(VKVG_LOG_ERR, "CREATE Device failed, provided vkvg_device_create_info_t is null\n");
+        return (VkvgDevice)&_vkvg_status_invalid_dev_ci;
+    }
     VkvgDevice dev = (vkvg_device *)calloc(1, sizeof(vkvg_device));
     if (!dev) {
         LOG(VKVG_LOG_ERR, "CREATE Device failed, no memory\n");
-        exit(-1);
+        return (VkvgDevice)&_vkvg_status_no_memory;
     }
 
     dev->references = 1;
 
+    dev->threadAware = info->threadAware;
+    if (dev->threadAware) {
+        mtx_init(&dev->mutex, mtx_plain);
+        mtx_init(&dev->fontCache->mutex, mtx_plain);
+        dev->threadAware = true;
+    }
+
     if (!info->vkdev) {
         const char *enabledExts[10];
         const char *enabledLayers[10];
@@ -337,6 +342,9 @@ VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info) {
             if (!_device_try_get_phyinfo(phys, phyCount, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, &pi))
                 pi = phys[0];
 
+        if (!info->samples) // if not set, default to 1 sample
+            info->samples = VK_SAMPLE_COUNT_1_BIT;
+
         if (!(pi->properties.limits.framebufferColorSampleCounts & info->samples)) {
             LOG(VKVG_LOG_ERR, "CREATE Device failed: sample count not supported: %d\n", info->samples);
             dev->status = VKVG_STATUS_DEVICE_ERROR;
@@ -388,6 +396,10 @@ VkvgDevice vkvg_device_create(vkvg_device_create_info_t *info) {
 }
 
 void vkvg_device_destroy(VkvgDevice dev) {
+    if (vkvg_device_status(dev)) {
+        LOG(VKVG_LOG_ERR, "DESTROY Device failed, see Status for info");
+        return;
+    }
     LOCK_DEVICE
     dev->references--;
     if (dev->references > 0) {
@@ -396,9 +408,13 @@ void vkvg_device_destroy(VkvgDevice dev) {
     }
     UNLOCK_DEVICE
 
+    LOG(VKVG_LOG_INFO, "DESTROY Device\n");
+
     if (dev->cachedContextCount > 0) {
         _cached_ctx *cur = dev->cachedContextLast;
         while (cur) {
+            assert(cur->ctx->status == VKVG_STATUS_IN_CACHE);
+            cur->ctx->status = VKVG_STATUS_SUCCESS;
             _release_context_ressources(cur->ctx);
             _cached_ctx *prev = cur;
             cur               = cur->pNext;
@@ -406,8 +422,6 @@ void vkvg_device_destroy(VkvgDevice dev) {
         }
     }
 
-    LOG(VKVG_LOG_INFO, "DESTROY Device\n");
-
     vkDeviceWaitIdle(dev->vkDev);
 
     vkh_image_destroy(dev->emptyImg);
@@ -449,8 +463,10 @@ void vkvg_device_destroy(VkvgDevice dev) {
     vmaDestroyAllocator(dev->allocator);
 #endif
 
-    if (dev->threadAware)
+    if (dev->threadAware) {
         mtx_destroy(&dev->mutex);
+        mtx_destroy(&dev->fontCache->mutex);
+    }
 
     if (dev->vkhDev) {
         VkhApp app = vkh_device_get_app(dev->vkhDev);
@@ -461,38 +477,38 @@ void vkvg_device_destroy(VkvgDevice dev) {
     free(dev);
 }
 
-vkvg_status_t vkvg_device_status(VkvgDevice dev) { return dev->status; }
+vkvg_status_t vkvg_device_status(VkvgDevice dev) { return !dev ? VKVG_STATUS_NULL_POINTER : dev->status; }
 VkvgDevice    vkvg_device_reference(VkvgDevice dev) {
-    LOCK_DEVICE
-    dev->references++;
-    UNLOCK_DEVICE
+    if (!vkvg_device_status(dev)) {
+        LOCK_DEVICE
+        dev->references++;
+        UNLOCK_DEVICE
+    }
     return dev;
 }
-uint32_t vkvg_device_get_reference_count(VkvgDevice dev) { return dev->references; }
-void     vkvg_device_set_dpy(VkvgDevice dev, int hdpy, int vdpy) {
+uint32_t vkvg_device_get_reference_count(VkvgDevice dev) { return vkvg_device_status(dev) ? 0 : dev->references; }
+// TODO dpy reorganisation
+void vkvg_device_set_dpy(VkvgDevice dev, int hdpy, int vdpy) {
+    if (vkvg_device_status(dev))
+        return;
     dev->hdpi = hdpy;
     dev->vdpi = vdpy;
 
     // TODO: reset font cache
 }
 void vkvg_device_get_dpy(VkvgDevice dev, int *hdpy, int *vdpy) {
+    if (vkvg_device_status(dev))
+        return;
     *hdpy = dev->hdpi;
     *vdpy = dev->vdpi;
 }
-void vkvg_device_set_thread_aware(VkvgDevice dev, uint32_t thread_aware) {
-    if (thread_aware) {
-        if (dev->threadAware)
-            return;
-        mtx_init(&dev->mutex, mtx_plain);
-        mtx_init(&dev->fontCache->mutex, mtx_plain);
-        dev->threadAware = true;
-    } else if (dev->threadAware) {
-        mtx_destroy(&dev->mutex);
-        mtx_destroy(&dev->fontCache->mutex);
-        dev->threadAware = false;
-    }
-}
 #if VKVG_DBG_STATS
-vkvg_debug_stats_t vkvg_device_get_stats(VkvgDevice dev) { return dev->debug_stats; }
-vkvg_debug_stats_t vkvg_device_reset_stats(VkvgDevice dev) { dev->debug_stats = (vkvg_debug_stats_t){0}; }
+vkvg_debug_stats_t vkvg_device_get_stats(VkvgDevice dev) {
+    return vkvg_device_status(dev) ? (vkvg_debug_stats_t){0} : dev->debug_stats;
+}
+void vkvg_device_reset_stats(VkvgDevice dev) {
+    if (vkvg_device_status(dev))
+        return;
+    dev->debug_stats = (vkvg_debug_stats_t){0};
+}
 #endif
index 1264d2ffe81cf271d30ca39a3a875a96ab2834f2..928b5b83b541f227dce0658680b967d9fad23ab5 100644 (file)
@@ -495,7 +495,7 @@ bool _device_init_function_pointers(VkvgDevice dev) {
         LOG(VKVG_LOG_ERR, "vkvg create device failed: 'VK_EXT_debug_utils' has to be loaded for Debug build\n");
         return false;
     }
-    vkh_device_init_debug_utils((VkhDevice)dev);
+    vkh_device_init_debug_utils((VkhDevice)&dev->vkDev);
 #endif
     CmdBindPipeline          = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindPipeline);
     CmdBindDescriptorSets    = GetVkProcAddress(dev->vkDev, dev->instance, vkCmdBindDescriptorSets);
@@ -519,7 +519,7 @@ bool _device_init_function_pointers(VkvgDevice dev) {
 
 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, format, 16, 16, tiling, VKH_MEMORY_USAGE_GPU_ONLY,
+    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,
index d17eae1a2f942209648c928ce138105dce0c2f68..aeddd29ea6c6b756601ce5f0975a3ff8997c6d36 100644 (file)
@@ -59,6 +59,7 @@ typedef struct _cached_ctx {
 } _cached_ctx;
 
 typedef struct _vkvg_device_t {
+    vkvg_status_t                    status;      /**< Current status of device, affected by last operation */
     VkDevice                         vkDev;       /**< Vulkan Logical Device */
     VkPhysicalDeviceMemoryProperties phyMemProps; /**< Vulkan Physical device memory properties */
     VkPhysicalDevice                 phy;         /**< Vulkan Physical device */
@@ -109,7 +110,6 @@ typedef struct _vkvg_device_t {
     VkhImage           emptyImg;        /**< prevent unbound descriptor to trigger Validation error 61 */
     VkSampleCountFlags samples;         /**< samples count common to all surfaces */
     bool               deferredResolve; /**< if true, resolve only on context destruction and set as source */
-    vkvg_status_t      status;          /**< Current status of device, affected by last operation */
 
     _font_cache_t *fontCache; /**< Store everything relative to common font caching system */
 
index 868f42b45e4d4876c1e590751391c51791c45585..ba3b687789017c2e162ae91b2f96076b54370443 100644 (file)
@@ -67,22 +67,24 @@ void _fonts_cache_create(VkvgDevice dev) {
     cache->texPixelSize = 1;
 #endif
 
+    VkhDevice vkhd = (VkhDevice)&dev->vkDev;
+
     cache->texLength = FONT_CACHE_INIT_LAYERS;
     cache->texture   = vkh_tex2d_array_create(
-        (VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, cache->texLength, VKH_MEMORY_USAGE_GPU_ONLY,
+        vkhd, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, cache->texLength, VKH_MEMORY_USAGE_GPU_ONLY,
         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
     vkh_image_create_descriptor(cache->texture, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT,
                                 VK_FILTER_NEAREST, VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
                                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
 
-    cache->uploadFence = vkh_fence_create((VkhDevice)dev);
+    cache->uploadFence = vkh_fence_create(vkhd);
 
     const uint32_t buffLength = FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize;
 
-    vkh_buffer_init((VkhDevice)dev, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, buffLength,
-                    &cache->buff, true);
+    vkh_buffer_init(vkhd, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, buffLength, &cache->buff,
+                    true);
 
-    cache->cmd = vkh_cmd_buff_create((VkhDevice)dev, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+    cache->cmd = vkh_cmd_buff_create(vkhd, dev->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
 
     // Set texture cache initial layout to shaderReadOnly to prevent error msg if cache is not fill
     const VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, cache->texLength};
@@ -111,7 +113,7 @@ void _increase_font_tex_array(VkvgDevice dev) {
 
     uint8_t  newSize = cache->texLength + FONT_CACHE_INIT_LAYERS;
     VkhImage newImg  = vkh_tex2d_array_create(
-        (VkhDevice)dev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, newSize, VKH_MEMORY_USAGE_GPU_ONLY,
+        (VkhDevice)&dev->vkDev, cache->texFormat, FONT_PAGE_SIZE, FONT_PAGE_SIZE, newSize, VKH_MEMORY_USAGE_GPU_ONLY,
         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
     vkh_image_create_descriptor(newImg, VK_IMAGE_VIEW_TYPE_2D_ARRAY, VK_IMAGE_ASPECT_COLOR_BIT, VK_FILTER_NEAREST,
                                 VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST,
index 3afbe43ff3ca7a3cc931fa38a5e583e3c75e94b6..bceecdb408975d8595c390e640f4ef42d786b355 100644 (file)
 #include <stdarg.h>
 #include <string.h>
 
+// should be supported by c11
+// #include <threads.h>
+// #include <stdatomic.h>
+
 #define _USE_MATH_DEFINES
 #include <math.h>
 
     vkvg_status_t status;
 } _vkvg_no_mem_struct;*/
 
-static vkvg_status_t _no_mem_status = VKVG_STATUS_NO_MEMORY;
+// static error value whose address is returned instead of vkvg object pointers to avoid null pointers.
+static vkvg_status_t _vkvg_status_no_memory       = VKVG_STATUS_NO_MEMORY;
+static vkvg_status_t _vkvg_status_null_pointer    = VKVG_STATUS_NULL_POINTER;
+static vkvg_status_t _vkvg_status_invalid_dev_ci  = VKVG_STATUS_INVALID_DEVICE_CREATE_INFO;
+static vkvg_status_t _vkvg_status_device_error    = VKVG_STATUS_DEVICE_ERROR;
+static vkvg_status_t _vkvg_status_invalid_surface = VKVG_STATUS_INVALID_SURFACE;
 
 #endif
index 2aad0917dec4d381f680964e78db1ea3d0f948c8..451f6e15969ad3032fb5d903ba010d3c4a898a79 100644 (file)
 #include "vkvg_pattern.h"
 
 VkvgPattern vkvg_pattern_create_for_surface(VkvgSurface surf) {
+    if (!surf) {
+        LOG(VKVG_LOG_ERR, "CREATE Pattern failed, invalid surface\n");
+        return (VkvgPattern)&_vkvg_status_null_pointer;
+    }
     VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
-    if (!pat)
-        return (VkvgPattern)&_no_mem_status;
+    if (!pat) {
+        LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
+        return (VkvgPattern)&_vkvg_status_null_pointer;
+    }
 
     pat->type       = VKVG_PATTERN_TYPE_SURFACE;
     pat->extend     = VKVG_EXTEND_NONE;
@@ -68,8 +74,10 @@ vkvg_status_t vkvg_pattern_edit_linear(VkvgPattern pat, float x0, float y0, floa
 }
 VkvgPattern vkvg_pattern_create_linear(float x0, float y0, float x1, float y1) {
     VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
-    if (!pat)
-        return (VkvgPattern)&_no_mem_status;
+    if (!pat) {
+        LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
+        return (VkvgPattern)&_vkvg_status_null_pointer;
+    }
     pat->type   = VKVG_PATTERN_TYPE_LINEAR;
     pat->extend = VKVG_EXTEND_NONE;
 
@@ -78,8 +86,9 @@ VkvgPattern vkvg_pattern_create_linear(float x0, float y0, float x1, float y1) {
     if (pat->data) {
         vkvg_pattern_edit_linear(pat, x0, y0, x1, y1);
         pat->references = 1;
-    } else
-        pat->status = VKVG_STATUS_NO_MEMORY;
+    } else {
+        pat->status = VKVG_STATUS_PATTERN_INVALID_GRADIENT;
+    }
 
     return pat;
 }
@@ -110,8 +119,10 @@ vkvg_status_t vkvg_pattern_edit_radial(VkvgPattern pat, float cx0, float cy0, fl
 }
 VkvgPattern vkvg_pattern_create_radial(float cx0, float cy0, float radius0, float cx1, float cy1, float radius1) {
     VkvgPattern pat = (vkvg_pattern_t *)calloc(1, sizeof(vkvg_pattern_t));
-    if (!pat)
-        return (VkvgPattern)&_no_mem_status;
+    if (!pat) {
+        LOG(VKVG_LOG_ERR, "CREATE Pattern failed, no memory\n");
+        return (VkvgPattern)&_vkvg_status_null_pointer;
+    }
     pat->type   = VKVG_PATTERN_TYPE_RADIAL;
     pat->extend = VKVG_EXTEND_NONE;
 
index fc281752c72476031c1ed3c7f505d48c133be36d..c52e722834ec16430c743252aa2158550986a53d 100644 (file)
 #include "stb_image_write.h"
 #include "vkh_image.h"
 
-#define max(x, y)
-void _transition_surf_images(VkvgSurface surf) {
-    LOCK_SURFACE(surf)
-    VkvgDevice dev = surf->dev;
-
-    //_surface_wait_cmd (surf);
-
-    vkh_cmd_begin(surf->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
-    VkhImage imgMs = surf->imgMS;
-    if (imgMs != NULL)
-        vkh_image_set_layout(surf->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
-                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
-                             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
-
-    vkh_image_set_layout(surf->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
-                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
-                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
-    vkh_image_set_layout(surf->cmd, surf->stencil, 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);
-    vkh_cmd_end(surf->cmd);
-
-    _surface_submit_cmd(surf);
-
-    UNLOCK_SURFACE(surf)
-}
 void vkvg_surface_clear(VkvgSurface surf) {
-    if (surf->status)
+    if (vkvg_surface_status(surf))
         return;
     _clear_surface(surf, VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_COLOR_BIT);
 }
@@ -70,11 +44,9 @@ VkvgSurface vkvg_surface_create(VkvgDevice dev, uint32_t width, uint32_t height)
     surf->newSurf = true; // used to clear all attacments on first render pass
 
     _create_surface_images(surf);
-
     _transition_surf_images(surf);
 
     surf->status = VKVG_STATUS_SUCCESS;
-    vkvg_device_reference(surf->dev);
     return surf;
 }
 VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *vkhImg) {
@@ -103,7 +75,6 @@ VkvgSurface vkvg_surface_create_for_VkhImage(VkvgDevice dev, void *vkhImg) {
     //_clear_surface                                           (surf, VK_IMAGE_ASPECT_STENCIL_BIT);
 
     surf->status = VKVG_STATUS_SUCCESS;
-    vkvg_device_reference(surf->dev);
     return surf;
 }
 // TODO: it would be better to blit in original size and create ms final image with dest surf dims
@@ -124,20 +95,20 @@ VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char *img,
     uint32_t                 imgSize         = width * height * 4;
     VkImageSubresourceLayers imgSubResLayers = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
     // original format image
-    VkhImage stagImg = vkh_image_create((VkhDevice)surf->dev, VK_FORMAT_R8G8B8A8_UNORM, surf->width, surf->height,
-                                        VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_ONLY,
+    VkhImage stagImg = vkh_image_create((VkhDevice)&surf->dev->vkDev, VK_FORMAT_R8G8B8A8_UNORM, surf->width,
+                                        surf->height, VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_ONLY,
                                         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
     // bgra bliting target
     VkhImage tmpImg =
-        vkh_image_create((VkhDevice)surf->dev, surf->format, surf->width, surf->height, VK_IMAGE_TILING_LINEAR,
+        vkh_image_create((VkhDevice)&surf->dev->vkDev, surf->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,
                                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER);
     // staging buffer
     vkh_buffer_t buff = {0};
-    vkh_buffer_init((VkhDevice)dev, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, imgSize, &buff,
-                    true);
+    vkh_buffer_init((VkhDevice)&dev->vkDev, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VKH_MEMORY_USAGE_CPU_TO_GPU, imgSize,
+                    &buff, true);
 
     memcpy(vkh_buffer_get_mapped_pointer(&buff), img, imgSize);
 
@@ -204,7 +175,6 @@ VkvgSurface vkvg_surface_create_from_bitmap(VkvgDevice dev, unsigned char *img,
     vkh_image_destroy(tmpImg);
 
     surf->status = VKVG_STATUS_SUCCESS;
-    vkvg_device_reference(surf->dev);
     return surf;
 }
 VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath) {
@@ -212,7 +182,7 @@ VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath)
     unsigned char *img = stbi_load(filePath, &w, &h, &channels, 4); // force 4 components per pixel
     if (!img) {
         LOG(VKVG_LOG_ERR, "Could not load texture from %s, %s\n", filePath, stbi_failure_reason());
-        return (VkvgSurface)&_no_mem_status;
+        return (VkvgSurface)&_vkvg_status_null_pointer;
     }
 
     VkvgSurface surf = vkvg_surface_create_from_bitmap(dev, img, (uint32_t)w, (uint32_t)h);
@@ -223,8 +193,14 @@ VkvgSurface vkvg_surface_create_from_image(VkvgDevice dev, const char *filePath)
 }
 
 void vkvg_surface_destroy(VkvgSurface surf) {
-    if (surf->status)
+    if (vkvg_surface_status(surf)) {
+        LOG(VKVG_LOG_ERR, "DESTROY surface failed, invalid surface\n");
+        return;
+    }
+    if (!surf->dev || surf->dev->status) {
+        LOG(VKVG_LOG_ERR, "DESTROY surface failed, device error\n");
         return;
+    }
 
     LOCK_SURFACE(surf)
     surf->references--;
@@ -234,6 +210,8 @@ void vkvg_surface_destroy(VkvgSurface surf) {
     }
     UNLOCK_SURFACE(surf)
 
+    LOG(VKVG_LOG_INFO, "DESTROY Surface\n");
+
     vkDestroyCommandPool(surf->dev->vkDev, surf->cmdPool, NULL);
     vkDestroyFramebuffer(surf->dev->vkDev, surf->fb, NULL);
 
@@ -256,8 +234,10 @@ void vkvg_surface_destroy(VkvgSurface surf) {
     free(surf);
 }
 
+vkvg_status_t vkvg_surface_status(VkvgSurface surf) { return !surf ? VKVG_STATUS_NULL_POINTER : surf->status; }
+
 VkvgSurface vkvg_surface_reference(VkvgSurface surf) {
-    if (!surf->status) {
+    if (!vkvg_surface_status(surf)) {
         LOCK_SURFACE(surf)
         surf->references++;
         UNLOCK_SURFACE(surf)
@@ -265,7 +245,7 @@ VkvgSurface vkvg_surface_reference(VkvgSurface surf) {
     return surf;
 }
 uint32_t vkvg_surface_get_reference_count(VkvgSurface surf) {
-    if (surf->status)
+    if (vkvg_surface_status(surf))
         return 0;
     return surf->references;
 }
@@ -323,11 +303,11 @@ vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char *path) {
     VkhImage stagImg;
 
     if (dev->pngStagTiling == VK_IMAGE_TILING_LINEAR)
-        stagImg = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+        stagImg = vkh_image_create((VkhDevice)&surf->dev->vkDev, dev->pngStagFormat, surf->width, surf->height,
                                    dev->pngStagTiling, VKH_MEMORY_USAGE_GPU_TO_CPU,
                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
     else
-        stagImg = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+        stagImg = vkh_image_create((VkhDevice)&surf->dev->vkDev, dev->pngStagFormat, surf->width, surf->height,
                                    dev->pngStagTiling, VKH_MEMORY_USAGE_GPU_ONLY,
                                    VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
 
@@ -356,7 +336,7 @@ vkvg_status_t vkvg_surface_write_to_png(VkvgSurface surf, const char *path) {
     VkhImage stagImgLinear = stagImg;
 
     if (dev->pngStagTiling == VK_IMAGE_TILING_OPTIMAL) {
-        stagImgLinear   = vkh_image_create((VkhDevice)surf->dev, dev->pngStagFormat, surf->width, surf->height,
+        stagImgLinear   = vkh_image_create((VkhDevice)&surf->dev->vkDev, dev->pngStagFormat, surf->width, surf->height,
                                            VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_TO_CPU,
                                            VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
         VkImageCopy cpy = {.srcSubresource = imgSubResLayers,
@@ -411,8 +391,8 @@ vkvg_status_t vkvg_surface_write_to_memory(VkvgSurface surf, unsigned char *cons
     VkvgDevice               dev             = surf->dev;
 
     // RGBA to blit to, surf img is bgra
-    VkhImage stagImg = vkh_image_create((VkhDevice)surf->dev, VK_FORMAT_B8G8R8A8_UNORM, surf->width, surf->height,
-                                        VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_TO_CPU,
+    VkhImage stagImg = vkh_image_create((VkhDevice)&surf->dev->vkDev, VK_FORMAT_B8G8R8A8_UNORM, surf->width,
+                                        surf->height, VK_IMAGE_TILING_LINEAR, VKH_MEMORY_USAGE_GPU_TO_CPU,
                                         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
 
     VkCommandBuffer cmd = surf->cmd;
index f1bf9dd688ad7cd6a08d9cf5f6c81bae959fbac9..69428a7c5015774dbbb36252383810e07426fe59 100644 (file)
@@ -53,7 +53,31 @@ void _explicit_ms_resolve(VkvgSurface surf) {
 
     UNLOCK_SURFACE(surf)
 }
+void _transition_surf_images(VkvgSurface surf) {
+    LOCK_SURFACE(surf)
+    VkvgDevice dev = surf->dev;
+
+    //_surface_wait_cmd (surf);
+
+    vkh_cmd_begin(surf->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
+    VkhImage imgMs = surf->imgMS;
+    if (imgMs != NULL)
+        vkh_image_set_layout(surf->cmd, imgMs, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+                             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
 
+    vkh_image_set_layout(surf->cmd, surf->img, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
+                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                         VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+    vkh_image_set_layout(surf->cmd, surf->stencil, 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);
+    vkh_cmd_end(surf->cmd);
+
+    _surface_submit_cmd(surf);
+
+    UNLOCK_SURFACE(surf)
+}
 void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect) {
     LOCK_SURFACE(surf)
 
@@ -102,41 +126,42 @@ void _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect) {
 }
 
 void _create_surface_main_image(VkvgSurface surf) {
-    surf->img = vkh_image_create((VkhDevice)surf->dev, surf->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);
+    VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev;
+    surf->img      = vkh_image_create(vkhd, surf->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);
     vkh_image_create_descriptor(surf->img, 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);
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
     vkh_image_set_name(surf->img, "SURF main color");
-    vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->img),
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->img),
                                "SURF main color VIEW");
-    vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->img),
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->img),
                                "SURF main color SAMPLER");
 #endif
 }
 // 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->dev->samples > VK_SAMPLE_COUNT_1_BIT) {
-        surf->imgMS = vkh_image_ms_create((VkhDevice)surf->dev, surf->format, surf->dev->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);
+        surf->imgMS = vkh_image_ms_create(
+            vkhd, surf->format, surf->dev->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,
                                     VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
         vkh_image_set_name(surf->imgMS, "SURF MS color IMG");
-        vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW,
-                                   (uint64_t)vkh_image_get_view(surf->imgMS), "SURF MS color VIEW");
-        vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER,
-                                   (uint64_t)vkh_image_get_sampler(surf->imgMS), "SURF MS color SAMPLER");
+        vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->imgMS),
+                                   "SURF MS color VIEW");
+        vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->imgMS),
+                                   "SURF MS color SAMPLER");
 #endif
     }
-    surf->stencil = vkh_image_ms_create((VkhDevice)surf->dev, surf->dev->stencilFormat, surf->dev->samples, surf->width,
-                                        surf->height, VKH_MEMORY_USAGE_GPU_ONLY,
+    surf->stencil = vkh_image_ms_create(vkhd, surf->dev->stencilFormat, surf->dev->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);
     vkh_image_create_descriptor(surf->stencil, VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_STENCIL_BIT, VK_FILTER_NEAREST,
@@ -144,10 +169,10 @@ void _create_surface_secondary_images(VkvgSurface surf) {
                                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
     vkh_image_set_name(surf->stencil, "SURF stencil");
-    vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_IMAGE_VIEW,
-                               (uint64_t)vkh_image_get_view(surf->stencil), "SURF stencil VIEW");
-    vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_SAMPLER,
-                               (uint64_t)vkh_image_get_sampler(surf->stencil), "SURF stencil SAMPLER");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)vkh_image_get_view(surf->stencil),
+                               "SURF stencil VIEW");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_SAMPLER, (uint64_t)vkh_image_get_sampler(surf->stencil),
+                               "SURF stencil SAMPLER");
 #endif
 }
 void _create_framebuffer(VkvgSurface surf) {
@@ -171,7 +196,7 @@ void _create_framebuffer(VkvgSurface surf) {
     }
     VK_CHECK_RESULT(vkCreateFramebuffer(surf->dev->vkDev, &frameBufferCreateInfo, NULL, &surf->fb));
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
-    vkh_device_set_object_name((VkhDevice)surf->dev, VK_OBJECT_TYPE_FRAMEBUFFER, (uint64_t)surf->fb, "SURF FB");
+    vkh_device_set_object_name((VkhDevice)&surf->dev->vkDev, VK_OBJECT_TYPE_FRAMEBUFFER, (uint64_t)surf->fb, "SURF FB");
 #endif
 }
 void _create_surface_images(VkvgSurface surf) {
@@ -180,40 +205,48 @@ void _create_surface_images(VkvgSurface surf) {
     _create_surface_secondary_images(surf);
     _create_framebuffer(surf);
 
-#if defined(DEBUG) && defined(ENABLE_VALIDATION)
+#if defined(DEBUG) && defined(VKVG_DBG_UTILS)
     vkh_image_set_name(surf->img, "surfImg");
     vkh_image_set_name(surf->imgMS, "surfImgMS");
     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)) {
+        LOG(VKVG_LOG_ERR, "CREATE Surface failed, invalid Device\n");
+        return (VkvgSurface)&_vkvg_status_device_error;
+    }
+
     VkvgSurface surf = (vkvg_surface *)calloc(1, sizeof(vkvg_surface));
-    if (!surf)
-        return (VkvgSurface)&_no_mem_status;
+    if (!surf) {
+        LOG(VKVG_LOG_ERR, "CREATE Surface failed, no memory\n");
+        return (VkvgSurface)&_vkvg_status_no_memory;
+    }
 
     surf->references = 1;
-    if (dev->status != VKVG_STATUS_SUCCESS) {
-        surf->status = VKVG_STATUS_DEVICE_ERROR;
-        return surf;
-    }
     surf->dev    = dev;
     surf->format = format;
+
     if (dev->threadAware)
         mtx_init(&surf->mutex, mtx_plain);
+
+    VkhDevice vkhd = (VkhDevice)&surf->dev->vkDev;
+
     surf->cmdPool =
-        vkh_cmd_pool_create((VkhDevice)dev, dev->gQueue->familyIndex, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
-    vkh_cmd_buffs_create((VkhDevice)dev, surf->cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1, &surf->cmd);
+        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);
 
 #if VKVG_ENABLE_VK_TIMELINE_SEMAPHORE
-    surf->timeline = vkh_timeline_create((VkhDevice)dev, 0);
+    surf->timeline = vkh_timeline_create(vkhd, 0);
 #else
-    surf->flushFence = vkh_fence_create((VkhDevice)dev);
+    surf->flushFence = vkh_fence_create(vkhd);
 #endif
 
 #if defined(DEBUG) && defined(VKVG_DBG_UTILS)
-    vkh_device_set_object_name((VkhDevice)dev, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd");
+    vkh_device_set_object_name(vkhd, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t)surf->cmd, "vkvgSurfCmd");
 #endif
-
+    vkvg_device_reference(surf->dev);
     return surf;
 }
 // if fence sync, surf mutex must be locked.
@@ -240,7 +273,7 @@ void _surface_submit_cmd(VkvgSurface surf) {
     vkh_cmd_submit_timelined(dev->gQueue, &surf->cmd, surf->timeline, surf->timelineStep, surf->timelineStep + 1);
     surf->timelineStep++;
     UNLOCK_DEVICE
-    vkh_timeline_wait((VkhDevice)dev, surf->timeline, surf->timelineStep);
+    vkh_timeline_wait((VkhDevice)&dev->vkDev, surf->timeline, surf->timelineStep);
 #else
     LOCK_DEVICE
     vkh_cmd_submit(surf->dev->gQueue, &surf->cmd, surf->flushFence);
index 085ce77b198766bb8e76aa9bfdd298b45f44e569..ef9c685f57ec2269c4cb30483fb71077e5980481 100644 (file)
@@ -51,13 +51,16 @@ typedef struct _vkvg_surface_t {
 } vkvg_surface;
 
 #define LOCK_SURFACE(surf)                                                                                             \
-    if (surf->dev->threadAware)                                                                                        \
-        mtx_lock(&surf->mutex);
+    if (surf->dev->threadAware) {                                                                                      \
+        mtx_lock(&surf->mutex);                                                                                        \
+    }
 #define UNLOCK_SURFACE(surf)                                                                                           \
-    if (surf->dev->threadAware)                                                                                        \
-        mtx_unlock(&surf->mutex);
+    if (surf->dev->threadAware) {                                                                                      \
+        mtx_unlock(&surf->mutex);                                                                                      \
+    }
 
 void        _explicit_ms_resolve(VkvgSurface surf);
+void        _transition_surf_images(VkvgSurface surf);
 void        _clear_surface(VkvgSurface surf, VkImageAspectFlags aspect);
 void        _create_surface_main_image(VkvgSurface surf);
 void        _create_surface_secondary_images(VkvgSurface surf);
index 02959939efdd71465a05676ab1c48d30b9d94d2b..7526b2ac02f5625e2efb6df3d48d9c92f04fff22 100644 (file)
@@ -558,12 +558,11 @@ void perform_test_onscreen(void (*testfunc)(void), const char *testName, int arg
     vkengine_set_cursor_pos_callback(e, mouse_move_callback);
     vkengine_set_scroll_callback(e, scroll_callback);
 
-    vkvg_device_create_info_t info = {samples, false, vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam, 0};
+    vkvg_device_create_info_t info = {samples, false,      vkh_app_get_inst(e->app), r->dev->phy, r->dev->dev, r->qFam,
+                                      0,       threadAware};
     device                         = vkvg_device_create(&info);
 
     vkvg_device_set_dpy(device, 96, 96);
-    if (threadAware)
-        vkvg_device_set_thread_aware(device, 1);
 
 #ifdef VKVG_TEST_DIRECT_DRAW
     surfaces = (VkvgSurface *)malloc(r->imgCount * sizeof(VkvgSurface));
diff --git a/tests/data/blender_icons16.png b/tests/data/blender_icons16.png
new file mode 100644 (file)
index 0000000..2f2f8de
Binary files /dev/null and b/tests/data/blender_icons16.png differ
index 280261de3d7809380b6dc35b3b12ed524a963f0b..728fe15a119efc884a32a9394e4a613870bcc3c5 100644 (file)
@@ -48,8 +48,6 @@ void fixedSizeRects() {
     mtx_t mutex;
     pmutex = &mutex;
 
-    vkvg_device_set_thread_aware(device, 1);
-
     thrd_t threads[THREAD_COUNT];
 
     finishedThreadCount = 0;
@@ -65,8 +63,6 @@ void fixedSizeRects() {
     mtx_unlock(pmutex);
     mtx_destroy(pmutex);
     pmutex = NULL;
-
-    vkvg_device_set_thread_aware(device, 0);
 }
 
 int main(int argc, char *argv[]) {
index 7eff7a0700a31023cd7593437541242a77b08923..61a87bed25be74304b582bc42dd0daeac7e7c059 100644 (file)
@@ -35,8 +35,6 @@ void fixedSizeRects() {
     mtx_t mutex;
     pmutex = &mutex;
 
-    vkvg_device_set_thread_aware(device, 1);
-
     thrd_t threads[THREAD_COUNT];
 
     finishedThreadCount = 0;
@@ -52,8 +50,6 @@ void fixedSizeRects() {
     mtx_unlock(pmutex);
     mtx_destroy(pmutex);
     pmutex = NULL;
-
-    vkvg_device_set_thread_aware(device, 0);
 }
 
 int main(int argc, char *argv[]) {
index f7e8d80b999fd514befbd682e6b0e27ca5ddde24..c8a587eab28014fe31169052325c66e8103f596c 100644 (file)
@@ -22,8 +22,6 @@ void fixedSizeRects() {
     mtx_t mutex;
     pmutex = &mutex;
 
-    vkvg_device_set_thread_aware(device, 1);
-
     thrd_t threads[THREAD_COUNT];
 
     finishedThreadCount = 0;
@@ -39,8 +37,6 @@ void fixedSizeRects() {
     mtx_unlock(pmutex);
     mtx_destroy(pmutex);
     pmutex = NULL;
-
-    vkvg_device_set_thread_aware(device, 0);
 }
 
 int main(int argc, char *argv[]) {
index 8ae18a9056c120055ef84e3aaecbd9f78dff851c..bba02804b66fe9fec139742638312fadaaa1b5ed 100644 (file)
@@ -53,8 +53,6 @@ void threaded_text(int (*testfunc)(void *)) {
     mtx_t mutex;
     pmutex = &mutex;
 
-    vkvg_device_set_thread_aware(device, 1);
-
     thrd_t threads[THREAD_COUNT];
 
     finishedThreadCount = 0;
@@ -70,8 +68,6 @@ void threaded_text(int (*testfunc)(void *)) {
     mtx_unlock(pmutex);
     mtx_destroy(pmutex);
     pmutex = NULL;
-
-    vkvg_device_set_thread_aware(device, 0);
 }
 void single_font_and_size() { threaded_text(_single_font_and_size); }
 
index 58651c9517475497469a583427fffc6b1bcbb371..dc2f1e07fe90b80afc63d9a7a56deb74e8463dc9 100644 (file)
@@ -1,6 +1,7 @@
 #include "test.h"
 
 float       lineWidth = 10.f;
+static float angle     = 0;
 const char *imgPath   = "data/miroir.jpg";
 
 VkvgPattern create_grad(VkvgContext ctx) {
@@ -47,6 +48,41 @@ void img_scale() {
     vkvg_surface_destroy(imgSurf);
 }
 
+void icon_sheet() {
+    VkvgSurface imgSurf = vkvg_surface_create_from_image(device, "data/blender_icons16.png");
+    VkvgPattern pat     = vkvg_pattern_create_for_surface(imgSurf);
+    VkvgContext ctx     = _initCtx(surf);
+
+    vkvg_translate(ctx, 100, 100);
+
+    vkvg_matrix_t mat;
+    // vkvg_matrix_init_rotate(&mat, 1.2f);
+    // vkvg_matrix_init_translate(&mat, 23.f, 0.f);
+
+    float scale = 0.5f;
+
+    // vkvg_matrix_init_scale(&mat, scale, scale);
+    // vkvg_matrix_rotate(&mat, -0.3f);
+    vkvg_matrix_init_translate(&mat, 22.0f, 27.0f);
+    vkvg_matrix_scale(&mat, scale, scale);
+    vkvg_matrix_rotate(&mat, 0.2f);
+
+    // vkvg_matrix_init_rotate(&mat, 0.14f);
+    vkvg_pattern_set_matrix(pat, &mat);
+
+    // vkvg_scale(ctx, 4.f, 4.f);
+    // vkvg_rotate(ctx, 0.5f);
+    vkvg_set_source(ctx, pat);
+
+    vkvg_rectangle(ctx, 0, 0, 24.f / scale, 24.f / scale);
+    // vkvg_rectangle(ctx, 0, 0, 602.f, 640.f);
+    // vkvg_rectangle(ctx, 0, 0, 24.f, 24.f);
+    vkvg_fill(ctx);
+    vkvg_destroy(ctx);
+    vkvg_pattern_destroy(pat);
+    vkvg_surface_destroy(imgSurf);
+}
+
 void pat_scale() {
 
     VkvgContext ctx = _initCtx(surf);
@@ -64,8 +100,8 @@ void pat_scale() {
     vkvg_destroy(ctx);
     vkvg_pattern_destroy(pat);
 }
-static float angle = 0;
-void         pat_rotate() {
+
+void pat_rotate() {
     angle += 0.001f;
 
     VkvgContext ctx = _initCtx(surf);
@@ -89,5 +125,6 @@ int main(int argc, char *argv[]) {
     PERFORM_TEST(pat_scale, argc, argv);
     PERFORM_TEST(pat_rotate, argc, argv);
     PERFORM_TEST(img_scale, argc, argv);
+    PERFORM_TEST(icon_sheet, argc, argv);
     return 0;
 }