swappyVk.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. * Copyright 2018 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @defgroup swappyVk Swappy for Vulkan
  18. * Vulkan part of Swappy.
  19. * @{
  20. */
  21. #pragma once
  22. #include "jni.h"
  23. #include "swappy_common.h"
  24. #ifndef VK_NO_PROTOTYPES
  25. #define VK_NO_PROTOTYPES 1
  26. #endif
  27. #include <vulkan/vulkan.h>
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. /**
  32. * @brief Determine any Vulkan device extensions that must be enabled for a new
  33. * VkDevice.
  34. *
  35. * Swappy-for-Vulkan (SwappyVk) benefits from certain Vulkan device extensions
  36. * (e.g. VK_GOOGLE_display_timing). Before the application calls
  37. * vkCreateDevice, SwappyVk needs to look at the list of available extensions
  38. * (returned by vkEnumerateDeviceExtensionProperties) and potentially identify
  39. * one or more extensions that the application must add to:
  40. *
  41. * - VkDeviceCreateInfo::enabledExtensionCount
  42. * - VkDeviceCreateInfo::ppEnabledExtensionNames
  43. *
  44. * before the application calls vkCreateDevice. For each VkPhysicalDevice that
  45. * the application will call vkCreateDevice for, the application must call this
  46. * function, and then must add the identified extension(s) to the list that are
  47. * enabled for the VkDevice. Similar to many Vulkan functions, this function
  48. * can be called twice, once to identify the number of required extensions, and
  49. * again with application-allocated memory that the function can write into.
  50. *
  51. * @param[in] physicalDevice - The VkPhysicalDevice associated with
  52. * the available extensions.
  53. * @param[in] availableExtensionCount - This is the returned value of
  54. * pPropertyCount from vkEnumerateDeviceExtensionProperties.
  55. * @param[in] pAvailableExtensions - This is the returned value of
  56. * pProperties from vkEnumerateDeviceExtensionProperties.
  57. * @param[inout] pRequiredExtensionCount - If pRequiredExtensions is nullptr,
  58. * the function sets this to the number of extensions that are required. If
  59. * pRequiredExtensions is non-nullptr, this is the number of required extensions
  60. * that the function should write into pRequiredExtensions.
  61. * @param[inout] pRequiredExtensions - If non-nullptr, this is
  62. * application-allocated memory into which the function will write the names of
  63. * required extensions. It is a pointer to an array of
  64. * char* strings (i.e. the same as
  65. * VkDeviceCreateInfo::ppEnabledExtensionNames).
  66. */
  67. void SwappyVk_determineDeviceExtensions(
  68. VkPhysicalDevice physicalDevice, uint32_t availableExtensionCount,
  69. VkExtensionProperties* pAvailableExtensions,
  70. uint32_t* pRequiredExtensionCount, char** pRequiredExtensions);
  71. /**
  72. * @brief Tell Swappy the queueFamilyIndex used to create a specific VkQueue
  73. *
  74. * Swappy needs to know the queueFamilyIndex used for creating a specific
  75. * VkQueue so it can use it when presenting.
  76. *
  77. * @param[in] device - The VkDevice associated with the queue
  78. * @param[in] queue - A device queue.
  79. * @param[in] queueFamilyIndex - The queue family index used to create the
  80. * VkQueue.
  81. *
  82. */
  83. void SwappyVk_setQueueFamilyIndex(VkDevice device, VkQueue queue,
  84. uint32_t queueFamilyIndex);
  85. // TBD: For now, SwappyVk assumes only one VkSwapchainKHR per VkDevice, and that
  86. // applications don't re-create swapchains. Is this long-term sufficient?
  87. /**
  88. * Internal init function. Do not call directly.
  89. * See SwappyVk_initAndGetRefreshCycleDuration instead.
  90. * @private
  91. */
  92. bool SwappyVk_initAndGetRefreshCycleDuration_internal(
  93. JNIEnv* env, jobject jactivity, VkPhysicalDevice physicalDevice,
  94. VkDevice device, VkSwapchainKHR swapchain, uint64_t* pRefreshDuration);
  95. /**
  96. * @brief Initialize SwappyVk for a given device and swapchain, and obtain the
  97. * approximate time duration between vertical-blanking periods.
  98. *
  99. * Uses JNI to query AppVsyncOffset and PresentationDeadline.
  100. *
  101. * If your application presents to more than one swapchain at a time, you must
  102. * call this for each swapchain before calling swappyVkSetSwapInterval() for it.
  103. *
  104. * The duration between vertical-blanking periods (an interval) is expressed as
  105. * the approximate number of nanoseconds between vertical-blanking periods of
  106. * the swapchain’s physical display.
  107. *
  108. * If the application converts this number to a fraction (e.g. 16,666,666 nsec
  109. * to 0.016666666) and divides one by that fraction, it will be the approximate
  110. * refresh rate of the display (e.g. 16,666,666 nanoseconds corresponds to a
  111. * 60Hz display, 11,111,111 nsec corresponds to a 90Hz display).
  112. *
  113. * @param[in] env - JNIEnv that is assumed to be from AttachCurrentThread
  114. * function
  115. * @param[in] jactivity - NativeActivity object handle, used for JNI
  116. * @param[in] physicalDevice - The VkPhysicalDevice associated with the
  117. * swapchain
  118. * @param[in] device - The VkDevice associated with the swapchain
  119. * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
  120. * swap
  121. * @param[out] pRefreshDuration - The returned refresh cycle duration
  122. *
  123. * @return bool - true if the value returned by pRefreshDuration is
  124. * valid, otherwise false if an error.
  125. */
  126. bool SwappyVk_initAndGetRefreshCycleDuration(JNIEnv* env, jobject jactivity,
  127. VkPhysicalDevice physicalDevice,
  128. VkDevice device,
  129. VkSwapchainKHR swapchain,
  130. uint64_t* pRefreshDuration);
  131. /**
  132. * @brief Tell Swappy which ANativeWindow to use when calling to ANativeWindow_*
  133. * API.
  134. * @param[in] device - The VkDevice associated with the swapchain
  135. * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
  136. * swap
  137. * @param[in] window - The ANativeWindow that was used to create the
  138. * VkSwapchainKHR
  139. */
  140. void SwappyVk_setWindow(VkDevice device, VkSwapchainKHR swapchain,
  141. ANativeWindow* window);
  142. /**
  143. * @brief Tell Swappy the duration of that each presented image should be
  144. * visible.
  145. *
  146. * If your application presents to more than one swapchain at a time, you must
  147. * call this for each swapchain before presenting to it.
  148. *
  149. * @param[in] device - The VkDevice associated with the swapchain
  150. * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
  151. * swap
  152. * @param[in] swap_ns - The duration of that each presented image should be
  153. * visible in nanoseconds
  154. */
  155. void SwappyVk_setSwapIntervalNS(VkDevice device, VkSwapchainKHR swapchain,
  156. uint64_t swap_ns);
  157. /**
  158. * @brief Tell Swappy to present one or more images to corresponding swapchains.
  159. *
  160. * Swappy will call vkQueuePresentKHR for your application. Swappy may insert a
  161. * struct to the pNext-chain of VkPresentInfoKHR, or it may insert other Vulkan
  162. * commands in order to attempt to honor the desired swap interval.
  163. *
  164. * @note If your application presents to more than one swapchain at a time, and
  165. * if you use a different swap interval for each swapchain, Swappy will attempt
  166. * to honor the swap interval for each swapchain (being more successful on
  167. * devices that support an underlying presentation-timing extension, such as
  168. * VK_GOOGLE_display_timing).
  169. *
  170. * @param[in] queue - The VkQueue associated with the device and swapchain
  171. * @param[in] pPresentInfo - A pointer to the VkPresentInfoKHR containing the
  172. * information about what image(s) to present on which
  173. * swapchain(s).
  174. */
  175. VkResult SwappyVk_queuePresent(VkQueue queue,
  176. const VkPresentInfoKHR* pPresentInfo);
  177. /**
  178. * @brief Destroy the SwappyVk instance associated with a swapchain.
  179. *
  180. * This API is expected to be called before calling vkDestroySwapchainKHR()
  181. * so Swappy can cleanup its internal state.
  182. *
  183. * @param[in] device - The VkDevice associated with SwappyVk
  184. * @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to
  185. * destroy
  186. */
  187. void SwappyVk_destroySwapchain(VkDevice device, VkSwapchainKHR swapchain);
  188. /**
  189. * @brief Destroy any swapchains associated with the device and clean up the
  190. * device's resources
  191. *
  192. * This function should be called after SwappyVk_destroySwapchain if you no
  193. * longer need the device.
  194. *
  195. * @param[in] device - The VkDevice associated with SwappyVk
  196. */
  197. void SwappyVk_destroyDevice(VkDevice device);
  198. /**
  199. * @brief Enables Auto-Swap-Interval feature for all instances.
  200. *
  201. * By default this feature is enabled. Changing it is completely
  202. * optional for fine-tuning swappy behaviour.
  203. *
  204. * @param[in] enabled - True means enable, false means disable
  205. */
  206. void SwappyVk_setAutoSwapInterval(bool enabled);
  207. /**
  208. * @brief Enables Auto-Pipeline-Mode feature for all instances.
  209. *
  210. * By default this feature is enabled. Changing it is completely
  211. * optional for fine-tuning swappy behaviour.
  212. *
  213. * @param[in] enabled - True means enable, false means disable
  214. */
  215. void SwappyVk_setAutoPipelineMode(bool enabled);
  216. /**
  217. * @brief Sets the maximal swap duration for all instances.
  218. *
  219. * Sets the maximal duration for Auto-Swap-Interval in milliseconds.
  220. * If SwappyVk is operating in Auto-Swap-Interval and the frame duration is
  221. * longer than the provided duration, SwappyVk will not do any pacing and just
  222. * submit the frame as soon as possible.
  223. *
  224. * @param[in] max_swap_ns - maximal swap duration in milliseconds.
  225. */
  226. void SwappyVk_setMaxAutoSwapIntervalNS(uint64_t max_swap_ns);
  227. /**
  228. * @brief The fence timeout parameter can be set for devices with faulty
  229. * drivers. Its default value is 50,000,000.
  230. */
  231. void SwappyVk_setFenceTimeoutNS(uint64_t fence_timeout_ns);
  232. /**
  233. * @brief Get the fence timeout parameter, for devices with faulty
  234. * drivers. Its default value is 50,000,000.
  235. */
  236. uint64_t SwappyVk_getFenceTimeoutNS();
  237. /**
  238. * @brief Inject callback functions to be called each frame.
  239. *
  240. * @param[in] tracer - Collection of callback functions
  241. */
  242. void SwappyVk_injectTracer(const SwappyTracer* tracer);
  243. /**
  244. * @brief Remove callbacks that were previously added using
  245. * SwappyVk_injectTracer.
  246. *
  247. * Only removes callbacks that were previously added using
  248. * SwappyVK_injectTracer. If SwappyVK_injectTracker was not called with the
  249. * tracer, then there is no effect.
  250. *
  251. * @param[in] tracer - Collection of callback functions
  252. */
  253. void SwappyVk_uninjectTracer(const SwappyTracer* tracer);
  254. /**
  255. * @brief A structure enabling you to provide your own Vulkan function wrappers
  256. * by calling ::SwappyVk_setFunctionProvider.
  257. *
  258. * Usage of this functionality is optional.
  259. */
  260. typedef struct SwappyVkFunctionProvider {
  261. /**
  262. * @brief Callback to initialize the function provider.
  263. *
  264. * This function is called by Swappy before any functions are requested.
  265. * E.g. so you can call dlopen on the Vulkan library.
  266. */
  267. bool (*init)();
  268. /**
  269. * @brief Callback to get the address of a function.
  270. *
  271. * This function is called by Swappy to get the address of a Vulkan
  272. * function.
  273. * @param name The null-terminated name of the function.
  274. */
  275. void* (*getProcAddr)(const char* name);
  276. /**
  277. * @brief Callback to close any resources owned by the function provider.
  278. *
  279. * This function is called by Swappy when no more functions will be
  280. * requested, e.g. so you can call dlclose on the Vulkan library.
  281. */
  282. void (*close)();
  283. } SwappyVkFunctionProvider;
  284. /**
  285. * @brief Set the Vulkan function provider.
  286. *
  287. * This enables you to provide an object that will be used to look up Vulkan
  288. * functions, e.g. to hook usage of these functions.
  289. *
  290. * To use this functionality, you *must* call this function before any others.
  291. *
  292. * Usage of this function is entirely optional. If you do not use it, the Vulkan
  293. * functions required by Swappy will be dynamically loaded from libvulkan.so.
  294. *
  295. * @param[in] provider - provider object
  296. */
  297. void SwappyVk_setFunctionProvider(
  298. const SwappyVkFunctionProvider* pSwappyVkFunctionProvider);
  299. /**
  300. * @brief Get the swap interval value, in nanoseconds, for a given swapchain.
  301. *
  302. * @param[in] swapchain - the swapchain to query
  303. */
  304. uint64_t SwappyVk_getSwapIntervalNS(VkSwapchainKHR swapchain);
  305. /**
  306. * @brief Get the supported refresh periods of this device. Call once with
  307. * out_refreshrates set to nullptr to get the number of supported refresh
  308. * periods, then call again passing that number as allocated_entries and
  309. * an array of size equal to allocated_entries that will be filled with the
  310. * refresh periods.
  311. */
  312. int SwappyVk_getSupportedRefreshPeriodsNS(uint64_t* out_refreshrates,
  313. int allocated_entries,
  314. VkSwapchainKHR swapchain);
  315. /**
  316. * @brief Check if Swappy is enabled for the specified swapchain.
  317. *
  318. * @return false if SwappyVk_initAndGetRefreshCycleDuration was not
  319. * called for the specified swapchain, true otherwise.
  320. */
  321. bool SwappyVk_isEnabled(VkSwapchainKHR swapchain, bool* isEnabled);
  322. /**
  323. * @brief Toggle statistics collection on/off
  324. *
  325. * By default, stats collection is off and there is no overhead related to
  326. * stats. An app can turn on stats collection by calling
  327. * `SwappyVk_enableStats(swapchain, true)`. Then, the app is expected to call
  328. * ::SwappyVk_recordFrameStart for each frame before starting to do any CPU
  329. * related work. Stats will be logged to logcat with a 'FrameStatistics' tag. An
  330. * app can get the stats by calling ::SwappyVk_getStats.
  331. *
  332. * SwappyVk_initAndGetRefreshCycleDuration must have been called successfully
  333. * before for this swapchain, otherwise there is no effect in this call. Frame
  334. * stats are only available if the platform supports VK_GOOGLE_display_timing
  335. * extension.
  336. *
  337. * @param[in] swapchain - The swapchain for which frame stat collection is
  338. * configured.
  339. * @param enabled - Whether to enable/disable frame stat collection.
  340. */
  341. void SwappyVk_enableStats(VkSwapchainKHR swapchain, bool enabled);
  342. /**
  343. * @brief Should be called if stats have been enabled with SwappyVk_enableStats.
  344. *
  345. * When stats collection is enabled with SwappyVk_enableStats, the app is
  346. * expected to call this function for each frame before starting to do any CPU
  347. * related work. It is assumed that this function will be called after a
  348. * successful call to vkAcquireNextImageKHR. See ::SwappyVk_enableStats for more
  349. * conditions.
  350. *
  351. * @param[in] queue - The VkQueue associated with the device and swapchain
  352. * @param[in] swapchain - The swapchain where the frame is presented to.
  353. * @param[in] image - The image in swapchain that corresponds to the frame.
  354. * @see SwappyVk_enableStats.
  355. */
  356. void SwappyVk_recordFrameStart(VkQueue queue, VkSwapchainKHR swapchain,
  357. uint32_t image);
  358. /**
  359. * @brief Returns the stats collected, if statistics collection was toggled on.
  360. *
  361. * Given that this API uses VkSwapchainKHR and the potential for this call to be
  362. * done on different threads, all calls to ::SwappyVk_getStats
  363. * must be externally synchronized with other SwappyVk calls. Unsynchronized
  364. * calls may lead to undefined behavior. See ::SwappyVk_enableStats for more
  365. * conditions.
  366. *
  367. * @param[in] swapchain - The swapchain for which stats are being queried.
  368. * @param swappyStats - Pointer to a SwappyStats that will be populated
  369. * with the collected stats. Cannot be NULL.
  370. * @see SwappyStats
  371. */
  372. void SwappyVk_getStats(VkSwapchainKHR swapchain, SwappyStats* swappyStats);
  373. /**
  374. * @brief Clears the frame statistics collected so far.
  375. *
  376. * All the frame statistics collected are reset to 0, frame statistics are
  377. * collected normally after this call. See ::SwappyVk_enableStats for more
  378. * conditions.
  379. *
  380. * @param[in] swapchain - The swapchain for which stats are being cleared.
  381. */
  382. void SwappyVk_clearStats(VkSwapchainKHR swapchain);
  383. /**
  384. * @brief Reset the swappy pacing mechanism
  385. *
  386. * In cases where the frame timing history is irrelevant (for example during
  387. * scene/level transitions or after loading screens), calling this would
  388. * remove all the history for frame pacing. Calling this entry point
  389. * would reset the frame rate to the initial state at the end of the current
  390. * frame. Then swappy would just pace as normal with fresh state from next
  391. * frame. There are no error conditions associated with this call.
  392. *
  393. * @param[in] swapchain - The swapchain for which frame pacing is reset.
  394. */
  395. void SwappyVk_resetFramePacing(VkSwapchainKHR swapchain);
  396. /**
  397. * @brief Enable/Disable the swappy pacing mechanism
  398. *
  399. * By default frame pacing is enabled when swappy is used, however it can be
  400. * disabled at runtime by calling `SwappyVk_enableFramePacing(swapchain,
  401. * false)`. When the frame pacing is disabled, ::SwappyVk_enableBlockingWait
  402. * will control whether
  403. * ::SwappyVk_queuePresent will return immediately, or will block until the
  404. * previous frame's GPU work is completed. All enabling/disabling effects take
  405. * place from next frame. Once disabled, `SwappyVk_enableFramePacing(swapchain,
  406. * true)` will enable frame pacing again with a fresh frame time state -
  407. * equivalent of calling ::SwappyVk_resetFramePacing().
  408. *
  409. * @param[in] swapchain - The swapchain for which stats are being queried.
  410. * @param enable - If true, enables frame pacing otherwise disables it
  411. */
  412. void SwappyVk_enableFramePacing(VkSwapchainKHR swapchain, bool enable);
  413. /**
  414. * @brief Enable/Disable blocking wait when frame-pacing is disabled
  415. *
  416. * By default ::SwappyVk_queuePresent will do a blocking wait until previous
  417. * frame's GPU work is completed. However when frame pacing is disabled, calling
  418. * `SwappyVk_enableBlockingWait(swapchain, false)` will ensure that
  419. * ::SwappyVk_queuePresent returns without waiting for previous frame's GPU
  420. * work. This behaviour impacts the GPU time returned in the
  421. * ::SwappyPostWaitCallback callback. If the last frame's GPU work is done by
  422. * the time ::SwappyVk_queuePresent for this frame is called, then the previous
  423. * frame's GPU time will be returned otherwise `-1` will be delivered in the
  424. * callback for the frame. This setting has no impact when frame pacing is
  425. * enabled.
  426. *
  427. * @param[in] swapchain - The swapchain for which stats are being queried.
  428. * @param enable - If true, ::SwappyVk_queuePresent will block until
  429. * the previous frame's GPU work is complete.
  430. */
  431. void SwappyVk_enableBlockingWait(VkSwapchainKHR swapchain, bool enable);
  432. #ifdef __cplusplus
  433. } // extern "C"
  434. #endif
  435. /** @} */