blob: 1be8d0bb82d23ef4897ff7269e7623ba266cdd4a [file] [log] [blame]
/*
* 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 "swappy_common.h"
#include "jni.h"
#define VK_NO_PROTOTYPES 1
#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.
*/
static inline bool SwappyVk_initAndGetRefreshCycleDuration(
JNIEnv* env,
jobject jactivity,
VkPhysicalDevice physicalDevice,
VkDevice device,
VkSwapchainKHR swapchain,
uint64_t* pRefreshDuration) {
// This call ensures that the header and the linked library are from the same version
// (if not, a linker error will be triggered because of an undefined symbol).
SWAPPY_VERSION_SYMBOL();
return SwappyVk_initAndGetRefreshCycleDuration_internal(env, jactivity, physicalDevice, device,
swapchain, pRefreshDuration);
}
/**
* @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 SwappyVk instance associated to the swapchain
*
* This API is expected to be called before calling to vkDestroySwapchainKHR()
* so Swappy can cleanup its internal state.
* Note that if you only have one swapchain for the device,
* this function will also clean up any resources associated with the device.
*
* @param[in] device - The VkDevice associated with SwappyVk
* @param[in] swapchain - The VkSwapchainKHR the application wants Swappy to swap
*/
void SwappyVk_destroySwapchain(
VkDevice device,
VkSwapchainKHR swapchain);
/**
* @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 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);
#ifdef __cplusplus
} // extern "C"
#endif
/** @} */