1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Update to latest version of Swappy

Fixes #103294

(cherry picked from commit 89ea5b3d00)
This commit is contained in:
Matias N. Goldberg
2025-02-28 15:01:07 -03:00
committed by Rémi Verschelde
parent b734db834a
commit 2bf9dc71da
6 changed files with 187 additions and 129 deletions

View File

@@ -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/fetch-gh-release-asset@1.1.2 uses: dsaltares/fetch-gh-release-asset@1.1.2
with: with:
repo: darksylinc/godot-swappy repo: godotengine/godot-swappy
version: tags/v2023.3.0.0 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
.gitignore vendored
View File

@@ -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/

View File

@@ -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"

View File

@@ -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) \ #define AGDK_STRINGIFY(NUMBER) #NUMBER
#MAJOR "." #MINOR "." #BUGFIX "." #GIT #define AGDK_STRING_VERSION(MAJOR, MINOR, BUGFIX) \
AGDK_STRINGIFY(MAJOR) "." AGDK_STRINGIFY(MINOR) "." AGDK_STRINGIFY(BUGFIX)

View File

@@ -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. * @brief Callback to initialize the function provider.
* *
* This function is called by Swappy before any functions are requested. * This function is called by Swappy before any functions are requested.
* E.g. so you can call dlopen on the Vulkan library. * E.g. so you can call dlopen on the Vulkan library.
*/ */
bool (*init)(); bool (*init)();
/** /**
* @brief Callback to get the address of a function. * @brief Callback to get the address of a function.
* *
* This function is called by Swappy to get the address of a Vulkan * This function is called by Swappy to get the address of a Vulkan
* function. * function.
* @param name The null-terminated name of the function. * @param name The null-terminated name of the function.
*/ */
void* (*getProcAddr)(const char* name); void* (*getProcAddr)(const char* name);
/** /**
* @brief Callback to close any resources owned by the function provider. * @brief Callback to close any resources owned by the function provider.
* *
* This function is called by Swappy when no more functions will be * This function is called by Swappy when no more functions will be
* requested, e.g. so you can call dlclose on the Vulkan library. * requested, e.g. so you can call dlclose on the Vulkan library.
*/ */
void (*close)(); 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 * @param swappyStats - Pointer to a SwappyStats that will be populated
* the collected stats. Cannot be NULL. * 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

View File

@@ -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 \ #define SWAPPY_PACKED_VERSION \
ANDROID_GAMESDK_PACKED_VERSION(SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION, \ ANDROID_GAMESDK_PACKED_VERSION(SWAPPY_MAJOR_VERSION, SWAPPY_MINOR_VERSION, \
SWAPPY_BUGFIX_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) SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT)
#define SWAPPY_VERSION_SYMBOL \ #define SWAPPY_VERSION_SYMBOL \
SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION, \ SWAPPY_VERSION_CONCAT(Swappy_version, SWAPPY_MAJOR_VERSION, \
SWAPPY_MINOR_VERSION, SWAPPY_BUGFIX_VERSION, \ SWAPPY_MINOR_VERSION, SWAPPY_BUGFIX_VERSION, \
AGDK_GIT_COMMIT) 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. /** @brief Thread start callback.
* *
* This function is called by Swappy to start thread_func on a new thread. * 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. * @param user_data A value to be passed the thread function.
* If the thread was started, this function should set the thread_id and * 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 * return 0. If the thread was not started, this function should return a
* non-zero value. * non-zero value.
*/ */
int (*start)(SwappyThreadId* thread_id, void* (*thread_func)(void*), int (*start)(SwappyThreadId* thread_id, void* (*thread_func)(void*),
void* user_data); void* user_data);
/** @brief Thread join callback. /** @brief Thread join callback.
* *
* This function is called by Swappy to join the thread with given id. * This function is called by Swappy to join the thread with given id.
*/ */
void (*join)(SwappyThreadId thread_id); void (*join)(SwappyThreadId thread_id);
/** @brief Thread joinable callback. /** @brief Thread joinable callback.
* *
* This function is called by Swappy to discover whether the thread with the * This function is called by Swappy to discover whether the thread with the
* given id is joinable. * given id is joinable.
*/ */
bool (*joinable)(SwappyThreadId thread_id); 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 */ /** @brief Total frames swapped by swappy */
uint64_t totalFrames; uint64_t totalFrames;
/** @brief Histogram of the number of screen refreshes a frame waited in the /** @brief Histogram of the number of screen refreshes a frame waited in the
* compositor queue after rendering was completed. * compositor queue after rendering was completed.
* *
* For example: * For example:
* if a frame waited 2 refresh periods in the compositor queue after * if a frame waited 2 refresh periods in the compositor queue after
* rendering was done, the frame will be counted in idleFrames[2] * rendering was done, the frame will be counted in idleFrames[2]
*/ */
uint64_t idleFrames[MAX_FRAME_BUCKETS]; uint64_t idleFrames[MAX_FRAME_BUCKETS];
/** @brief Histogram of the number of screen refreshes passed between the /** @brief Histogram of the number of screen refreshes passed between the
* requested presentation time and the actual present time. * requested presentation time and the actual present time.
* *
* For example: * For example:
* if a frame was presented 2 refresh periods after the requested * if a frame was presented 2 refresh periods after the requested
* timestamp swappy set, the frame will be counted in lateFrames[2] * timestamp swappy set, the frame will be counted in lateFrames[2]
*/ */
uint64_t lateFrames[MAX_FRAME_BUCKETS]; uint64_t lateFrames[MAX_FRAME_BUCKETS];
/** @brief Histogram of the number of screen refreshes passed between two /** @brief Histogram of the number of screen refreshes passed between two
* consecutive frames * consecutive frames
* *
* For example: * For example:
* if frame N was presented 2 refresh periods after frame N-1 * if frame N was presented 2 refresh periods after frame N-1
* frame N will be counted in offsetFromPreviousFrame[2] * frame N will be counted in offsetFromPreviousFrame[2]
*/ */
uint64_t offsetFromPreviousFrame[MAX_FRAME_BUCKETS]; uint64_t offsetFromPreviousFrame[MAX_FRAME_BUCKETS];
/** @brief Histogram of the number of screen refreshes passed between the /** @brief Histogram of the number of screen refreshes passed between the
* call to Swappy_recordFrameStart and the actual present time. * call to Swappy_recordFrameStart and the actual present time.
* *
* For example: * For example:
* if a frame was presented 2 refresh periods after the call to * if a frame was presented 2 refresh periods after the call to
* `Swappy_recordFrameStart` the frame will be counted in latencyFrames[2] * `Swappy_recordFrameStart` the frame will be counted in latencyFrames[2]
*/ */
uint64_t latencyFrames[MAX_FRAME_BUCKETS]; 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. * Callback called before waiting to queue the frame to the composer.
*/ */
SwappyPreWaitCallback preWait; SwappyPreWaitCallback preWait;
/** /**
* Callback called after wait to queue the frame to the composer is done. * Callback called after wait to queue the frame to the composer is done.
*/ */
SwappyPostWaitCallback postWait; SwappyPostWaitCallback postWait;
/** /**
* Callback called before calling the function to queue the frame to the * Callback called before calling the function to queue the frame to the
* composer. * composer.
*/ */
SwappyPreSwapBuffersCallback preSwapBuffers; SwappyPreSwapBuffersCallback preSwapBuffers;
/** /**
* Callback called after calling the function to queue the frame to the * Callback called after calling the function to queue the frame to the
* composer. * composer.
*/ */
SwappyPostSwapBuffersCallback postSwapBuffers; SwappyPostSwapBuffersCallback postSwapBuffers;
/** /**
* Callback called at the start of a frame. * Callback called at the start of a frame.
*/ */
SwappyStartFrameCallback startFrame; SwappyStartFrameCallback startFrame;
/** /**
* Pointer to some arbitrary data that will be passed as the first argument * Pointer to some arbitrary data that will be passed as the first argument
* of callbacks. * of callbacks.
*/ */
void* userData; void* userData;
/** /**
* Callback called when the swap interval was changed. * Callback called when the swap interval was changed.
*/ */
SwappySwapIntervalChangedCallback swapIntervalChanged; SwappySwapIntervalChangedCallback swapIntervalChanged;
} SwappyTracer; } SwappyTracer;
/** @} */ /** @} */