initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

215
thirdparty/swappy-frame-pacing/LICENSE vendored Normal file
View File

@@ -0,0 +1,215 @@
Copyright 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This is the main interface to the Android Performance Tuner library, also
* known as Tuning Fork.
*
* It is part of the Android Games SDK and produces best results when integrated
* with the Swappy Frame Pacing Library.
*
* See the documentation at
* https://developer.android.com/games/sdk/performance-tuner/custom-engine for
* more information on using this library in a native Android game.
*
*/
#pragma once
// There are separate versions for each GameSDK component that use this format:
#define ANDROID_GAMESDK_PACKED_VERSION(MAJOR, MINOR, BUGFIX) \
((MAJOR << 16) | (MINOR << 8) | (BUGFIX))
// Accessors
#define ANDROID_GAMESDK_MAJOR_VERSION(PACKED) ((PACKED) >> 16)
#define ANDROID_GAMESDK_MINOR_VERSION(PACKED) (((PACKED) >> 8) & 0xff)
#define ANDROID_GAMESDK_BUGFIX_VERSION(PACKED) ((PACKED) & 0xff)
#define AGDK_STRINGIFY(NUMBER) #NUMBER
#define AGDK_STRING_VERSION(MAJOR, MINOR, BUGFIX) \
AGDK_STRINGIFY(MAJOR) "." AGDK_STRINGIFY(MINOR) "." AGDK_STRINGIFY(BUGFIX)

View File

@@ -0,0 +1,473 @@
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @defgroup swappyVk Swappy for Vulkan
* Vulkan part of Swappy.
* @{
*/
#pragma once
#include "jni.h"
#include "swappy_common.h"
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES 1
#endif
#include <vulkan/vulkan.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Determine any Vulkan device extensions that must be enabled for a new
* VkDevice.
*
* Swappy-for-Vulkan (SwappyVk) benefits from certain Vulkan device extensions
* (e.g. VK_GOOGLE_display_timing). Before the application calls
* vkCreateDevice, SwappyVk needs to look at the list of available extensions
* (returned by vkEnumerateDeviceExtensionProperties) and potentially identify
* one or more extensions that the application must add to:
*
* - VkDeviceCreateInfo::enabledExtensionCount
* - VkDeviceCreateInfo::ppEnabledExtensionNames
*
* before the application calls vkCreateDevice. For each VkPhysicalDevice that
* the application will call vkCreateDevice for, the application must call this
* function, and then must add the identified extension(s) to the list that are
* enabled for the VkDevice. Similar to many Vulkan functions, this function
* can be called twice, once to identify the number of required extensions, and
* again with application-allocated memory that the function can write into.
*
* @param[in] physicalDevice - The VkPhysicalDevice associated with
* the available extensions.
* @param[in] availableExtensionCount - This is the returned value of
* pPropertyCount from vkEnumerateDeviceExtensionProperties.
* @param[in] pAvailableExtensions - This is the returned value of
* pProperties from vkEnumerateDeviceExtensionProperties.
* @param[inout] pRequiredExtensionCount - If pRequiredExtensions is nullptr,
* the function sets this to the number of extensions that are required. If
* pRequiredExtensions is non-nullptr, this is the number of required extensions
* that the function should write into pRequiredExtensions.
* @param[inout] pRequiredExtensions - If non-nullptr, this is
* application-allocated memory into which the function will write the names of
* required extensions. It is a pointer to an array of
* char* strings (i.e. the same as
* VkDeviceCreateInfo::ppEnabledExtensionNames).
*/
void SwappyVk_determineDeviceExtensions(
VkPhysicalDevice physicalDevice, uint32_t availableExtensionCount,
VkExtensionProperties* pAvailableExtensions,
uint32_t* pRequiredExtensionCount, char** pRequiredExtensions);
/**
* @brief Tell Swappy the queueFamilyIndex used to create a specific VkQueue
*
* Swappy needs to know the queueFamilyIndex used for creating a specific
* VkQueue so it can use it when presenting.
*
* @param[in] device - The VkDevice associated with the queue
* @param[in] queue - A device queue.
* @param[in] queueFamilyIndex - The queue family index used to create the
* VkQueue.
*
*/
void SwappyVk_setQueueFamilyIndex(VkDevice device, VkQueue queue,
uint32_t queueFamilyIndex);
// TBD: For now, SwappyVk assumes only one VkSwapchainKHR per VkDevice, and that
// applications don't re-create swapchains. Is this long-term sufficient?
/**
* Internal init function. Do not call directly.
* See SwappyVk_initAndGetRefreshCycleDuration instead.
* @private
*/
bool SwappyVk_initAndGetRefreshCycleDuration_internal(
JNIEnv* env, jobject jactivity, VkPhysicalDevice physicalDevice,
VkDevice device, VkSwapchainKHR swapchain, uint64_t* pRefreshDuration);
/**
* @brief Initialize SwappyVk for a given device and swapchain, and obtain the
* approximate time duration between vertical-blanking periods.
*
* Uses JNI to query AppVsyncOffset and PresentationDeadline.
*
* If your application presents to more than one swapchain at a time, you must
* call this for each swapchain before calling swappyVkSetSwapInterval() for it.
*
* The duration between vertical-blanking periods (an interval) is expressed as
* the approximate number of nanoseconds between vertical-blanking periods of
* the swapchains physical display.
*
* If the application converts this number to a fraction (e.g. 16,666,666 nsec
* to 0.016666666) and divides one by that fraction, it will be the approximate
* refresh rate of the display (e.g. 16,666,666 nanoseconds corresponds to a
* 60Hz display, 11,111,111 nsec corresponds to a 90Hz display).
*
* @param[in] env - JNIEnv that is assumed to be from AttachCurrentThread
* function
* @param[in] jactivity - NativeActivity object handle, used for JNI
* @param[in] physicalDevice - The VkPhysicalDevice associated with the
* swapchain
* @param[in] device - The VkDevice associated with the swapchain
* @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
* swap
* @param[out] pRefreshDuration - The returned refresh cycle duration
*
* @return bool - true if the value returned by pRefreshDuration is
* valid, otherwise false if an error.
*/
bool SwappyVk_initAndGetRefreshCycleDuration(JNIEnv* env, jobject jactivity,
VkPhysicalDevice physicalDevice,
VkDevice device,
VkSwapchainKHR swapchain,
uint64_t* pRefreshDuration);
/**
* @brief Tell Swappy which ANativeWindow to use when calling to ANativeWindow_*
* API.
* @param[in] device - The VkDevice associated with the swapchain
* @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
* swap
* @param[in] window - The ANativeWindow that was used to create the
* VkSwapchainKHR
*/
void SwappyVk_setWindow(VkDevice device, VkSwapchainKHR swapchain,
ANativeWindow* window);
/**
* @brief Tell Swappy the duration of that each presented image should be
* visible.
*
* If your application presents to more than one swapchain at a time, you must
* call this for each swapchain before presenting to it.
*
* @param[in] device - The VkDevice associated with the swapchain
* @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
* swap
* @param[in] swap_ns - The duration of that each presented image should be
* visible in nanoseconds
*/
void SwappyVk_setSwapIntervalNS(VkDevice device, VkSwapchainKHR swapchain,
uint64_t swap_ns);
/**
* @brief Tell Swappy to present one or more images to corresponding swapchains.
*
* Swappy will call vkQueuePresentKHR for your application. Swappy may insert a
* struct to the pNext-chain of VkPresentInfoKHR, or it may insert other Vulkan
* commands in order to attempt to honor the desired swap interval.
*
* @note If your application presents to more than one swapchain at a time, and
* if you use a different swap interval for each swapchain, Swappy will attempt
* to honor the swap interval for each swapchain (being more successful on
* devices that support an underlying presentation-timing extension, such as
* VK_GOOGLE_display_timing).
*
* @param[in] queue - The VkQueue associated with the device and swapchain
* @param[in] pPresentInfo - A pointer to the VkPresentInfoKHR containing the
* information about what image(s) to present on which
* swapchain(s).
*/
VkResult SwappyVk_queuePresent(VkQueue queue,
const VkPresentInfoKHR* pPresentInfo);
/**
* @brief Destroy the SwappyVk instance associated with a swapchain.
*
* This API is expected to be called before calling vkDestroySwapchainKHR()
* so Swappy can cleanup its internal state.
*
* @param[in] device - The VkDevice associated with SwappyVk
* @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
* destroy
*/
void SwappyVk_destroySwapchain(VkDevice device, VkSwapchainKHR swapchain);
/**
* @brief Destroy any swapchains associated with the device and clean up the
* device's resources
*
* This function should be called after SwappyVk_destroySwapchain if you no
* longer need the device.
*
* @param[in] device - The VkDevice associated with SwappyVk
*/
void SwappyVk_destroyDevice(VkDevice device);
/**
* @brief Enables Auto-Swap-Interval feature for all instances.
*
* By default this feature is enabled. Changing it is completely
* optional for fine-tuning swappy behaviour.
*
* @param[in] enabled - True means enable, false means disable
*/
void SwappyVk_setAutoSwapInterval(bool enabled);
/**
* @brief Enables Auto-Pipeline-Mode feature for all instances.
*
* By default this feature is enabled. Changing it is completely
* optional for fine-tuning swappy behaviour.
*
* @param[in] enabled - True means enable, false means disable
*/
void SwappyVk_setAutoPipelineMode(bool enabled);
/**
* @brief Sets the maximal swap duration for all instances.
*
* Sets the maximal duration for Auto-Swap-Interval in milliseconds.
* If SwappyVk is operating in Auto-Swap-Interval and the frame duration is
* longer than the provided duration, SwappyVk will not do any pacing and just
* submit the frame as soon as possible.
*
* @param[in] max_swap_ns - maximal swap duration in milliseconds.
*/
void SwappyVk_setMaxAutoSwapIntervalNS(uint64_t max_swap_ns);
/**
* @brief The fence timeout parameter can be set for devices with faulty
* drivers. Its default value is 50,000,000.
*/
void SwappyVk_setFenceTimeoutNS(uint64_t fence_timeout_ns);
/**
* @brief Get the fence timeout parameter, for devices with faulty
* drivers. Its default value is 50,000,000.
*/
uint64_t SwappyVk_getFenceTimeoutNS();
/**
* @brief Inject callback functions to be called each frame.
*
* @param[in] tracer - Collection of callback functions
*/
void SwappyVk_injectTracer(const SwappyTracer* tracer);
/**
* @brief Remove callbacks that were previously added using
* SwappyVk_injectTracer.
*
* Only removes callbacks that were previously added using
* SwappyVK_injectTracer. If SwappyVK_injectTracker was not called with the
* tracer, then there is no effect.
*
* @param[in] tracer - Collection of callback functions
*/
void SwappyVk_uninjectTracer(const SwappyTracer* tracer);
/**
* @brief A structure enabling you to provide your own Vulkan function wrappers
* by calling ::SwappyVk_setFunctionProvider.
*
* Usage of this functionality is optional.
*/
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)();
} SwappyVkFunctionProvider;
/**
* @brief Set the Vulkan function provider.
*
* This enables you to provide an object that will be used to look up Vulkan
* functions, e.g. to hook usage of these functions.
*
* To use this functionality, you *must* call this function before any others.
*
* Usage of this function is entirely optional. If you do not use it, the Vulkan
* functions required by Swappy will be dynamically loaded from libvulkan.so.
*
* @param[in] provider - provider object
*/
void SwappyVk_setFunctionProvider(
const SwappyVkFunctionProvider* pSwappyVkFunctionProvider);
/**
* @brief Get the swap interval value, in nanoseconds, for a given swapchain.
*
* @param[in] swapchain - the swapchain to query
*/
uint64_t SwappyVk_getSwapIntervalNS(VkSwapchainKHR swapchain);
/**
* @brief Get the supported refresh periods of this device. Call once with
* out_refreshrates set to nullptr to get the number of supported refresh
* periods, then call again passing that number as allocated_entries and
* an array of size equal to allocated_entries that will be filled with the
* refresh periods.
*/
int SwappyVk_getSupportedRefreshPeriodsNS(uint64_t* out_refreshrates,
int allocated_entries,
VkSwapchainKHR swapchain);
/**
* @brief Check if Swappy is enabled for the specified swapchain.
*
* @return false if SwappyVk_initAndGetRefreshCycleDuration was not
* called for the specified swapchain, true otherwise.
*/
bool SwappyVk_isEnabled(VkSwapchainKHR swapchain, bool* isEnabled);
/**
* @brief Toggle statistics collection on/off
*
* By default, stats collection is off and there is no overhead related to
* stats. An app can turn on stats collection by calling
* `SwappyVk_enableStats(swapchain, true)`. Then, the app is expected to call
* ::SwappyVk_recordFrameStart for each frame before starting to do any CPU
* related work. Stats will be logged to logcat with a 'FrameStatistics' tag. An
* app can get the stats by calling ::SwappyVk_getStats.
*
* SwappyVk_initAndGetRefreshCycleDuration must have been called successfully
* before for this swapchain, otherwise there is no effect in this call. Frame
* stats are only available if the platform supports VK_GOOGLE_display_timing
* extension.
*
* @param[in] swapchain - The swapchain for which frame stat collection is
* configured.
* @param enabled - Whether to enable/disable frame stat collection.
*/
void SwappyVk_enableStats(VkSwapchainKHR swapchain, bool enabled);
/**
* @brief Should be called if stats have been enabled with SwappyVk_enableStats.
*
* When stats collection is enabled with SwappyVk_enableStats, the app is
* expected to call this function for each frame before starting to do any CPU
* related work. It is assumed that this function will be called after a
* successful call to vkAcquireNextImageKHR. See ::SwappyVk_enableStats for more
* conditions.
*
* @param[in] queue - The VkQueue associated with the device and swapchain
* @param[in] swapchain - The swapchain where the frame is presented to.
* @param[in] image - The image in swapchain that corresponds to the frame.
* @see SwappyVk_enableStats.
*/
void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain,
uint32_t image);
/**
* @brief Returns the stats collected, if statistics collection was toggled on.
*
* Given that this API uses VkSwapchainKHR and the potential for this call to be
* done on different threads, all calls to ::SwappyVk_getStats
* must be externally synchronized with other SwappyVk calls. Unsynchronized
* calls may lead to undefined behavior. See ::SwappyVk_enableStats for more
* conditions.
*
* @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.
* @see SwappyStats
*/
void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats* swappyStats);
/**
* @brief Clears the frame statistics collected so far.
*
* All the frame statistics collected are reset to 0, frame statistics are
* collected normally after this call. See ::SwappyVk_enableStats for more
* conditions.
*
* @param[in] swapchain - The swapchain for which stats are being cleared.
*/
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
} // extern "C"
#endif
/** @} */

View File

@@ -0,0 +1,277 @@
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @defgroup swappy_common Swappy common tools
* Tools to be used with Swappy for OpenGL or Swappy for Vulkan.
* @{
*/
#pragma once
#include <android/native_window.h>
#include <stdint.h>
#include "common/gamesdk_common.h"
/** @brief Swap interval for 60fps, in nanoseconds. */
#define SWAPPY_SWAP_60FPS (16666667L)
/** @brief Swap interval for 30fps, in nanoseconds. */
#define SWAPPY_SWAP_30FPS (33333333L)
/** @brief Swap interval for 20fps, in nanoseconds. */
#define SWAPPY_SWAP_20FPS (50000000L)
/**
* The longest duration, in refresh periods, represented by the statistics.
* @see SwappyStats
*/
#define MAX_FRAME_BUCKETS 6
/** @cond INTERNAL */
#define SWAPPY_SYSTEM_PROP_KEY_DISABLE "swappy.disable"
// Internal macros to track Swappy version, do not use directly.
#define SWAPPY_MAJOR_VERSION 2
#define SWAPPY_MINOR_VERSION 2
#define SWAPPY_BUGFIX_VERSION 0
#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
// directly.
#define SWAPPY_VERSION_CONCAT_NX(PREFIX, MAJOR, MINOR, BUGFIX, GITCOMMIT) \
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)
// 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.
#ifndef ENABLE_SWAPPY_LOGGING
#define ENABLE_SWAPPY_LOGGING 0
#endif
/** @endcond */
/** @brief Id of a thread returned by an external thread manager. */
typedef uint64_t SwappyThreadId;
/**
* @brief A structure enabling you to set how Swappy starts and joins threads by
* calling
* ::Swappy_setThreadFunctions.
*
* Usage of this functionality is optional.
*/
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);
} SwappyThreadFunctions;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Return the version of the Swappy library at runtime.
*/
uint32_t Swappy_version();
/**
* @brief Call this before any other functions in order to use a custom thread
* manager.
*
* Usage of this function is entirely optional. Swappy uses std::thread by
* default.
*
*/
void Swappy_setThreadFunctions(const SwappyThreadFunctions* thread_functions);
/**
* @brief Return the full version of the Swappy library at runtime, e.g.
* "1.9.0_8a85ab7c46"
*/
const char* Swappy_versionString();
/**
* @brief Swappy frame statistics, collected if toggled on with
* ::SwappyGL_enableStats or ::SwappyVk_enableStats.
*/
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];
} SwappyStats;
#ifdef __cplusplus
} // extern "C"
#endif
/**
* Pointer to a function that can be attached to SwappyTracer::preWait
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
*/
typedef void (*SwappyPreWaitCallback)(void*);
/**
* Pointer to a function that can be attached to SwappyTracer::postWait.
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
* @param cpu_time_ns Time for CPU processing of this frame in nanoseconds.
* @param gpu_time_ns Time for GPU processing of previous frame in nanoseconds.
*/
typedef void (*SwappyPostWaitCallback)(void*, int64_t cpu_time_ns,
int64_t gpu_time_ns);
/**
* Pointer to a function that can be attached to SwappyTracer::preSwapBuffers.
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
*/
typedef void (*SwappyPreSwapBuffersCallback)(void*);
/**
* Pointer to a function that can be attached to SwappyTracer::postSwapBuffers.
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
* @param desiredPresentationTimeMillis The target time, in milliseconds, at
* which the frame would be presented on screen.
*/
typedef void (*SwappyPostSwapBuffersCallback)(
void*, int64_t desiredPresentationTimeMillis);
/**
* Pointer to a function that can be attached to SwappyTracer::startFrame.
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
* @param desiredPresentationTimeMillis The time, in milliseconds, at which the
* frame is scheduled to be presented.
*/
typedef void (*SwappyStartFrameCallback)(void*, int currentFrame,
int64_t desiredPresentationTimeMillis);
/**
* Pointer to a function that can be attached to
* SwappyTracer::swapIntervalChanged. Call ::SwappyGL_getSwapIntervalNS or
* ::SwappyVk_getSwapIntervalNS to get the latest swapInterval.
* @param userData Pointer to arbitrary data, see SwappyTracer::userData.
*/
typedef void (*SwappySwapIntervalChangedCallback)(void*);
/**
* @brief Collection of callbacks to be called each frame to trace execution.
*
* Injection of these is optional.
*/
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;
} SwappyTracer;
/** @} */