123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- /*
- * 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 swapchain’s 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
- /** @} */
|