浏览代码

Update to latest version of Swappy

Fixes #103294

(cherry picked from commit 89ea5b3d005126a2f7c463f7f487c5001d1b949e)
Matias N. Goldberg 4 月之前
父节点
当前提交
2bf9dc71da

+ 2 - 2
.github/workflows/android_builds.yml

@@ -62,8 +62,8 @@ jobs:
       - name: Download pre-built Android Swappy Frame Pacing Library
       - name: Download pre-built Android Swappy Frame Pacing Library
         uses: dsaltares/[email protected]
         uses: dsaltares/[email protected]
         with:
         with:
-          repo: darksylinc/godot-swappy
-          version: tags/v2023.3.0.0
+          repo: godotengine/godot-swappy
+          version: tags/from-source-2025-01-31
           file: godot-swappy.7z
           file: godot-swappy.7z
           target: swappy/godot-swappy.7z
           target: swappy/godot-swappy.7z
 
 

+ 5 - 0
.gitignore

@@ -263,6 +263,11 @@ bld/
 !thirdparty/**/arm/
 !thirdparty/**/arm/
 !thirdparty/**/arm64/
 !thirdparty/**/arm64/
 
 
+thirdparty/swappy-frame-pacing/arm64-v8a/abi.json
+thirdparty/swappy-frame-pacing/armeabi-v7a/abi.json
+thirdparty/swappy-frame-pacing/x86/abi.json
+thirdparty/swappy-frame-pacing/x86_64/abi.json
+
 # Visual Studio 2015/2017 cache/options directory
 # Visual Studio 2015/2017 cache/options directory
 .vs/
 .vs/
 
 

+ 1 - 1
platform/android/detect.py

@@ -187,7 +187,7 @@ def configure(env: "SConsEnvironment"):
     has_swappy = detect_swappy()
     has_swappy = detect_swappy()
     if not has_swappy:
     if not has_swappy:
         print_warning(
         print_warning(
-            "Swappy Frame Pacing not detected! It is strongly recommended you download it from https://github.com/darksylinc/godot-swappy/releases and extract it so that the following files can be found:\n"
+            "Swappy Frame Pacing not detected! It is strongly recommended you download it from https://github.com/godotengine/godot-swappy/releases and extract it so that the following files can be found:\n"
             + " thirdparty/swappy-frame-pacing/arm64-v8a/libswappy_static.a\n"
             + " thirdparty/swappy-frame-pacing/arm64-v8a/libswappy_static.a\n"
             + " thirdparty/swappy-frame-pacing/armeabi-v7a/libswappy_static.a\n"
             + " thirdparty/swappy-frame-pacing/armeabi-v7a/libswappy_static.a\n"
             + " thirdparty/swappy-frame-pacing/x86/libswappy_static.a\n"
             + " thirdparty/swappy-frame-pacing/x86/libswappy_static.a\n"

+ 4 - 3
thirdparty/swappy-frame-pacing/common/gamesdk_common.h

@@ -31,11 +31,12 @@
 
 
 // There are separate versions for each GameSDK component that use this format:
 // There are separate versions for each GameSDK component that use this format:
 #define ANDROID_GAMESDK_PACKED_VERSION(MAJOR, MINOR, BUGFIX) \
 #define ANDROID_GAMESDK_PACKED_VERSION(MAJOR, MINOR, BUGFIX) \
-    ((MAJOR << 16) | (MINOR << 8) | (BUGFIX))
+  ((MAJOR << 16) | (MINOR << 8) | (BUGFIX))
 // Accessors
 // Accessors
 #define ANDROID_GAMESDK_MAJOR_VERSION(PACKED) ((PACKED) >> 16)
 #define ANDROID_GAMESDK_MAJOR_VERSION(PACKED) ((PACKED) >> 16)
 #define ANDROID_GAMESDK_MINOR_VERSION(PACKED) (((PACKED) >> 8) & 0xff)
 #define ANDROID_GAMESDK_MINOR_VERSION(PACKED) (((PACKED) >> 8) & 0xff)
 #define ANDROID_GAMESDK_BUGFIX_VERSION(PACKED) ((PACKED) & 0xff)
 #define ANDROID_GAMESDK_BUGFIX_VERSION(PACKED) ((PACKED) & 0xff)
 
 
-#define AGDK_STRING_VERSION(MAJOR, MINOR, BUGFIX, GIT) \
-#MAJOR "." #MINOR "." #BUGFIX "." #GIT
+#define AGDK_STRINGIFY(NUMBER) #NUMBER
+#define AGDK_STRING_VERSION(MAJOR, MINOR, BUGFIX) \
+  AGDK_STRINGIFY(MAJOR) "." AGDK_STRINGIFY(MINOR) "." AGDK_STRINGIFY(BUGFIX)

+ 81 - 28
thirdparty/swappy-frame-pacing/swappyVk.h

@@ -281,30 +281,30 @@ void SwappyVk_uninjectTracer(const SwappyTracer* tracer);
  * Usage of this functionality is optional.
  * Usage of this functionality is optional.
  */
  */
 typedef struct SwappyVkFunctionProvider {
 typedef struct SwappyVkFunctionProvider {
-    /**
-     * @brief Callback to initialize the function provider.
-     *
-     * This function is called by Swappy before any functions are requested.
-     * E.g. so you can call dlopen on the Vulkan library.
-     */
-    bool (*init)();
-
-    /**
-     * @brief Callback to get the address of a function.
-     *
-     * This function is called by Swappy to get the address of a Vulkan
-     * function.
-     * @param name The null-terminated name of the function.
-     */
-    void* (*getProcAddr)(const char* name);
-
-    /**
-     * @brief Callback to close any resources owned by the function provider.
-     *
-     * This function is called by Swappy when no more functions will be
-     * requested, e.g. so you can call dlclose on the Vulkan library.
-     */
-    void (*close)();
+  /**
+   * @brief Callback to initialize the function provider.
+   *
+   * This function is called by Swappy before any functions are requested.
+   * E.g. so you can call dlopen on the Vulkan library.
+   */
+  bool (*init)();
+
+  /**
+   * @brief Callback to get the address of a function.
+   *
+   * This function is called by Swappy to get the address of a Vulkan
+   * function.
+   * @param name The null-terminated name of the function.
+   */
+  void* (*getProcAddr)(const char* name);
+
+  /**
+   * @brief Callback to close any resources owned by the function provider.
+   *
+   * This function is called by Swappy when no more functions will be
+   * requested, e.g. so you can call dlclose on the Vulkan library.
+   */
+  void (*close)();
 } SwappyVkFunctionProvider;
 } SwappyVkFunctionProvider;
 
 
 /**
 /**
@@ -384,7 +384,8 @@ void SwappyVk_enableStats(VkSwapchainKHR swapchain, bool enabled);
 
 
  * @see SwappyVk_enableStats.
  * @see SwappyVk_enableStats.
  */
  */
-void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain, uint32_t image);
+void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain,
+                               uint32_t image);
 
 
 /**
 /**
  * @brief Returns the stats collected, if statistics collection was toggled on.
  * @brief Returns the stats collected, if statistics collection was toggled on.
@@ -396,11 +397,11 @@ void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain, uint32_t
  * conditions.
  * conditions.
  *
  *
  * @param[in]  swapchain   - The swapchain for which stats are being queried.
  * @param[in]  swapchain   - The swapchain for which stats are being queried.
- * @param      swappyStats - Pointer to a SwappyStats that will be populated with
- *                             the collected stats. Cannot be NULL.
+ * @param      swappyStats - Pointer to a SwappyStats that will be populated
+ * with the collected stats. Cannot be NULL.
  * @see SwappyStats
  * @see SwappyStats
  */
  */
-void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats *swappyStats);
+void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats* swappyStats);
 
 
 /**
 /**
  * @brief Clears the frame statistics collected so far.
  * @brief Clears the frame statistics collected so far.
@@ -413,6 +414,58 @@ void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats *swappyStats);
  */
  */
 void SwappyVk_clearStats(VkSwapchainKHR swapchain);
 void SwappyVk_clearStats(VkSwapchainKHR swapchain);
 
 
+/**
+ * @brief Reset the swappy pacing mechanism
+ *
+ * In cases where the frame timing history is irrelevant (for example during
+ * scene/level transitions or after loading screens), calling this would
+ * remove all the history for frame pacing. Calling this entry point
+ * would reset the frame rate to the initial state at the end of the current
+ * frame. Then swappy would just pace as normal with fresh state from next
+ * frame. There are no error conditions associated with this call.
+ *
+ * @param[in]  swapchain   - The swapchain for which frame pacing is reset.
+ */
+void SwappyVk_resetFramePacing(VkSwapchainKHR swapchain);
+
+/**
+ * @brief Enable/Disable the swappy pacing mechanism
+ *
+ * By default frame pacing is enabled when swappy is used, however it can be
+ * disabled at runtime by calling `SwappyVk_enableFramePacing(swapchain,
+ * false)`. When the frame pacing is disabled, ::SwappyVk_enableBlockingWait
+ * will control whether
+ * ::SwappyVk_queuePresent will return immediately, or will block until the
+ * previous frame's GPU work is completed. All enabling/disabling effects take
+ * place from next frame. Once disabled, `SwappyVk_enableFramePacing(swapchain,
+ * true)` will enable frame pacing again with a fresh frame time state -
+ * equivalent of calling ::SwappyVk_resetFramePacing().
+ *
+ * @param[in]  swapchain   - The swapchain for which stats are being queried.
+ * @param      enable      - If true, enables frame pacing otherwise disables it
+ */
+void SwappyVk_enableFramePacing(VkSwapchainKHR swapchain, bool enable);
+
+/**
+ * @brief Enable/Disable blocking wait when frame-pacing is disabled
+ *
+ * By default ::SwappyVk_queuePresent will do a blocking wait until previous
+ * frame's GPU work is completed. However when frame pacing is disabled, calling
+ * `SwappyVk_enableBlockingWait(swapchain, false)` will ensure that
+ * ::SwappyVk_queuePresent returns without waiting for previous frame's GPU
+ * work. This behaviour impacts the GPU time returned in the
+ * ::SwappyPostWaitCallback callback. If the last frame's GPU work is done by
+ * the time ::SwappyVk_queuePresent for this frame is called, then the previous
+ * frame's GPU time will be returned otherwise `-1` will be delivered in the
+ * callback for the frame. This setting has no impact when frame pacing is
+ * enabled.
+ *
+ * @param[in]  swapchain   - The swapchain for which stats are being queried.
+ * @param      enable      - If true, ::SwappyVk_queuePresent will block until
+ * the previous frame's GPU work is complete.
+ */
+void SwappyVk_enableBlockingWait(VkSwapchainKHR swapchain, bool enable);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }  // extern "C"
 }  // extern "C"
 #endif
 #endif

+ 108 - 109
thirdparty/swappy-frame-pacing/swappy_common.h

@@ -48,22 +48,22 @@
 
 
 // Internal macros to track Swappy version, do not use directly.
 // Internal macros to track Swappy version, do not use directly.
 #define SWAPPY_MAJOR_VERSION 2
 #define SWAPPY_MAJOR_VERSION 2
-#define SWAPPY_MINOR_VERSION 0
+#define SWAPPY_MINOR_VERSION 2
 #define SWAPPY_BUGFIX_VERSION 0
 #define SWAPPY_BUGFIX_VERSION 0
-#define SWAPPY_PACKED_VERSION                                                  \
-    ANDROID_GAMESDK_PACKED_VERSION(SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION, \
-                                   SWAPPY_BUGFIX_VERSION)
+#define SWAPPY_PACKED_VERSION                                                \
+  ANDROID_GAMESDK_PACKED_VERSION(SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION, \
+                                 SWAPPY_BUGFIX_VERSION)
 
 
 // Internal macros to generate a symbol to track Swappy version, do not use
 // Internal macros to generate a symbol to track Swappy version, do not use
 // directly.
 // directly.
 #define SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \
 #define SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \
-    PREFIX##_##MAJOR##_##MINOR##_##BUGFIX##_##GITCOMMIT
+  PREFIX##_##MAJOR##_##MINOR##_##BUGFIX##_##GITCOMMIT
 #define SWAPPY_VERSION_CONCAT(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \
 #define SWAPPY_VERSION_CONCAT(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \
-    SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT)
-#define SWAPPY_VERSION_SYMBOL                                          \
-    SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION,        \
-                          SWAPPY_MINOR_VERSION, SWAPPY_BUGFIX_VERSION, \
-                          AGDK_GIT_COMMIT)
+  SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT)
+#define SWAPPY_VERSION_SYMBOL                                        \
+  SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION,        \
+                        SWAPPY_MINOR_VERSION, SWAPPY_BUGFIX_VERSION, \
+                        AGDK_GIT_COMMIT)
 
 
 // Define this to 1 to enable all logging from Swappy, by default it is
 // Define this to 1 to enable all logging from Swappy, by default it is
 // disabled in a release build and enabled in a debug build.
 // disabled in a release build and enabled in a debug build.
@@ -83,29 +83,29 @@ typedef uint64_t SwappyThreadId;
  * Usage of this functionality is optional.
  * Usage of this functionality is optional.
  */
  */
 typedef struct SwappyThreadFunctions {
 typedef struct SwappyThreadFunctions {
-    /** @brief Thread start callback.
-     *
-     * This function is called by Swappy to start thread_func on a new thread.
-     * @param user_data A value to be passed the thread function.
-     * If the thread was started, this function should set the thread_id and
-     * return 0. If the thread was not started, this function should return a
-     * non-zero value.
-     */
-    int (*start)(SwappyThreadId* thread_id, void* (*thread_func)(void*),
-                 void* user_data);
-
-    /** @brief Thread join callback.
-     *
-     * This function is called by Swappy to join the thread with given id.
-     */
-    void (*join)(SwappyThreadId thread_id);
-
-    /** @brief Thread joinable callback.
-     *
-     * This function is called by Swappy to discover whether the thread with the
-     * given id is joinable.
-     */
-    bool (*joinable)(SwappyThreadId thread_id);
+  /** @brief Thread start callback.
+   *
+   * This function is called by Swappy to start thread_func on a new thread.
+   * @param user_data A value to be passed the thread function.
+   * If the thread was started, this function should set the thread_id and
+   * return 0. If the thread was not started, this function should return a
+   * non-zero value.
+   */
+  int (*start)(SwappyThreadId* thread_id, void* (*thread_func)(void*),
+               void* user_data);
+
+  /** @brief Thread join callback.
+   *
+   * This function is called by Swappy to join the thread with given id.
+   */
+  void (*join)(SwappyThreadId thread_id);
+
+  /** @brief Thread joinable callback.
+   *
+   * This function is called by Swappy to discover whether the thread with the
+   * given id is joinable.
+   */
+  bool (*joinable)(SwappyThreadId thread_id);
 } SwappyThreadFunctions;
 } SwappyThreadFunctions;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -138,47 +138,46 @@ const char* Swappy_versionString();
  * ::SwappyGL_enableStats or ::SwappyVk_enableStats.
  * ::SwappyGL_enableStats or ::SwappyVk_enableStats.
  */
  */
 typedef struct SwappyStats {
 typedef struct SwappyStats {
-    /** @brief Total frames swapped by swappy */
-    uint64_t totalFrames;
-
-    /** @brief Histogram of the number of screen refreshes a frame waited in the
-     * compositor queue after rendering was completed.
-     *
-     * For example:
-     *     if a frame waited 2 refresh periods in the compositor queue after
-     * rendering was done, the frame will be counted in idleFrames[2]
-     */
-    uint64_t idleFrames[MAX_FRAME_BUCKETS];
-
-    /** @brief Histogram of the number of screen refreshes passed between the
-     * requested presentation time and the actual present time.
-     *
-     * For example:
-     *     if a frame was presented 2 refresh periods after the requested
-     * timestamp swappy set, the frame will be counted in lateFrames[2]
-     */
-    uint64_t lateFrames[MAX_FRAME_BUCKETS];
-
-    /** @brief Histogram of the number of screen refreshes passed between two
-     * consecutive frames
-     *
-     * For example:
-     *     if frame N was presented 2 refresh periods after frame N-1
-     *     frame N will be counted in offsetFromPreviousFrame[2]
-     */
-    uint64_t offsetFromPreviousFrame[MAX_FRAME_BUCKETS];
-
-    /** @brief Histogram of the number of screen refreshes passed between the
-     * call to Swappy_recordFrameStart and the actual present time.
-     *
-     * For example:
-     *     if a frame was presented 2 refresh periods after the call to
-     * `Swappy_recordFrameStart` the frame will be counted in latencyFrames[2]
-     */
-    uint64_t latencyFrames[MAX_FRAME_BUCKETS];
+  /** @brief Total frames swapped by swappy */
+  uint64_t totalFrames;
+
+  /** @brief Histogram of the number of screen refreshes a frame waited in the
+   * compositor queue after rendering was completed.
+   *
+   * For example:
+   *     if a frame waited 2 refresh periods in the compositor queue after
+   * rendering was done, the frame will be counted in idleFrames[2]
+   */
+  uint64_t idleFrames[MAX_FRAME_BUCKETS];
+
+  /** @brief Histogram of the number of screen refreshes passed between the
+   * requested presentation time and the actual present time.
+   *
+   * For example:
+   *     if a frame was presented 2 refresh periods after the requested
+   * timestamp swappy set, the frame will be counted in lateFrames[2]
+   */
+  uint64_t lateFrames[MAX_FRAME_BUCKETS];
+
+  /** @brief Histogram of the number of screen refreshes passed between two
+   * consecutive frames
+   *
+   * For example:
+   *     if frame N was presented 2 refresh periods after frame N-1
+   *     frame N will be counted in offsetFromPreviousFrame[2]
+   */
+  uint64_t offsetFromPreviousFrame[MAX_FRAME_BUCKETS];
+
+  /** @brief Histogram of the number of screen refreshes passed between the
+   * call to Swappy_recordFrameStart and the actual present time.
+   *
+   * For example:
+   *     if a frame was presented 2 refresh periods after the call to
+   * `Swappy_recordFrameStart` the frame will be counted in latencyFrames[2]
+   */
+  uint64_t latencyFrames[MAX_FRAME_BUCKETS];
 } SwappyStats;
 } SwappyStats;
 
 
-
 #ifdef __cplusplus
 #ifdef __cplusplus
 }  // extern "C"
 }  // extern "C"
 #endif
 #endif
@@ -236,43 +235,43 @@ typedef void (*SwappySwapIntervalChangedCallback)(void*);
  * Injection of these is optional.
  * Injection of these is optional.
  */
  */
 typedef struct SwappyTracer {
 typedef struct SwappyTracer {
-    /**
-     * Callback called before waiting to queue the frame to the composer.
-     */
-    SwappyPreWaitCallback preWait;
-
-    /**
-     * Callback called after wait to queue the frame to the composer is done.
-     */
-    SwappyPostWaitCallback postWait;
-
-    /**
-     * Callback called before calling the function to queue the frame to the
-     * composer.
-     */
-    SwappyPreSwapBuffersCallback preSwapBuffers;
-
-    /**
-     * Callback called after calling the function to queue the frame to the
-     * composer.
-     */
-    SwappyPostSwapBuffersCallback postSwapBuffers;
-
-    /**
-     * Callback called at the start of a frame.
-     */
-    SwappyStartFrameCallback startFrame;
-
-    /**
-     * Pointer to some arbitrary data that will be passed as the first argument
-     * of callbacks.
-     */
-    void* userData;
-
-    /**
-     * Callback called when the swap interval was changed.
-     */
-    SwappySwapIntervalChangedCallback swapIntervalChanged;
+  /**
+   * Callback called before waiting to queue the frame to the composer.
+   */
+  SwappyPreWaitCallback preWait;
+
+  /**
+   * Callback called after wait to queue the frame to the composer is done.
+   */
+  SwappyPostWaitCallback postWait;
+
+  /**
+   * Callback called before calling the function to queue the frame to the
+   * composer.
+   */
+  SwappyPreSwapBuffersCallback preSwapBuffers;
+
+  /**
+   * Callback called after calling the function to queue the frame to the
+   * composer.
+   */
+  SwappyPostSwapBuffersCallback postSwapBuffers;
+
+  /**
+   * Callback called at the start of a frame.
+   */
+  SwappyStartFrameCallback startFrame;
+
+  /**
+   * Pointer to some arbitrary data that will be passed as the first argument
+   * of callbacks.
+   */
+  void* userData;
+
+  /**
+   * Callback called when the swap interval was changed.
+   */
+  SwappySwapIntervalChangedCallback swapIntervalChanged;
 } SwappyTracer;
 } SwappyTracer;
 
 
 /** @} */
 /** @} */