Используйте следующие функции, чтобы использовать Android Frame Pacing с механизмом рендеринга на основе API Vulkan.
Определить необходимые расширения для создания
Чтобы собрать набор расширений, необходимых для создания экземпляра Android Frame Pacing при использовании Vulkan, выполните шаги, показанные в следующем фрагменте кода:
VkPhysicalDevice physicalDevice; uint32_t availableExtensionCount; VkExtensionProperties* pAvailableExtensions; uint32_t requiredExtensionCount; char** pRequiredExtensions; // Determine the number of extensions available for this device. vkEnumerateDeviceExtensionProperties(physicalDevice, layerName, &availableExtensionCount, pAvailableExtensions); // Determine the number of required extensions. SwappyVk_determineDeviceExtensions(physicalDevice, availableExtensionCount, pAvailableExtensions, &requiredExtensionCount, nullptr); // Determine the required extensions. pRequiredExtensions = (char**)malloc(requiredExtensionCount * sizeof(char*)); pRequiredExtensionsData = (char*)malloc(requiredExtensionCount * (VK_MAX_EXTENSION_NAME_SIZE + 1)); for (uint32_t i = 0; i < requiredExtensionCount; i++) { pRequiredExtensions[i] = &pRequiredExtensionsData[i * (VK_MAX_EXTENSION_NAME_SIZE + 1)]; } SwappyVk_determineDeviceExtensions(physicalDevice, availableExtensionCount, pAvailableExtensions, &requiredExtensionCount, pRequiredExtensions);
Затем вы можете запустить Android Frame Pacing, вызвав vkCreateDevice()
. Второй аргумент, структура типа VkDeviceCreateInfo*
, должен иметь элемент enabledExtensionCount
, равный количеству требуемых расширений.
Определить семейство очередей
Чтобы представить правильную очередь отображения, Android Frame Pacing должен знать, какое семейство очередей использует Vulkan. Чтобы определить правильное семейство, выполните шаги, показанные в следующем фрагменте кода:
// Reusing local variables from previous snippets: // VkPhysicalDevice physicalDevice; const VkDeviceCreateInfo createInfo; const VkAllocationCallbacks allocator; VkDevice device; uint32_t queueFamilyIndex; uint32_t queueIndex; VkQueue deviceQueue; // Values of "device" and "deviceQueue" set in the 1st and 2nd function // calls, respectively. vkCreateDevice(physicalDevice, &createInfo, &allocator, &device); vkGetDeviceQueue(device, queueFamilyIndex, queueIndex, &deviceQueue); SwappyVk_setQueueFamilyIndex(device, deviceQueue, queueFamilyIndex);
Определить частоту кадров для swapchain
Чтобы инициализировать Android Frame Pacing для данного физического устройства и цепочки обмена, выполните шаги, показанные в следующем фрагменте кода:
// Reusing local variables from previous snippets: // VkPhysicalDevice physicalDevice; // VkDevice device; // Assume that the JNI environment is available in: // JNIEnv *env; // jobject jactivity; // Assume that swapchain is already known. VkSwapchainKHR swapchain; uint64_t refreshDuration; // in nanoseconds // Determine duration between vertical-blanking periods. // Example: 60 FPS sets "refreshDuration" to 16,666,666. SwappyVk_initAndGetRefreshCycleDuration(env, jactivity, physicalDevice, device, swapchain, &refreshDuration);
Это определяет продолжительность подкачки в наносекундах. В swappy_common.h
определены вспомогательные макросы для обычной длительности подкачки (например, SWAPPY_SWAP_60FPS
).
Далее вам необходимо указать продолжительность подкачки в наносекундах.
// Declare the periods in nanoseconds that should elapse before refreshing one // image with the next image. There are helper macros defined in swappy_common.h // for common swap durations. // This example shows what to do when you want to render your game at 30 FPS. SwappyVk_setSwapIntervalNS(device, swapchain, SWAPPY_SWAP_30FPS);
Установка ANativeWindow
Swappy нужен дескриптор ANativeWindow
для выполнения специфичной для ANativeWindow
операции, такой как вызов ANativeWindow_setFrameRate()
. Вызовите SwappyVk_setWindow()
когда поверхность отображения вашего Android изменилась и у вас есть новый дескриптор ANativeWindow
(пример см. в примере Cube ).
Автоматические режимы
Android Frame Pacing регулирует продолжительность замены и режим конвейера на основе средней продолжительности предыдущих кадров. Вы можете контролировать это поведение с помощью следующих функций:
-
void SwappyVk_setAutoSwapInterval(bool enabled);
-
void SwappyVk_setMaxAutoSwapIntervalNS(uint64_t max_swap_ns);
-
void SwappyVk_setAutoPipelineMode(bool enabled);
Представить кадр
Чтобы представить кадр вашей игры в Android Frame Pacing, вызовите SwappyVk_queuePresent()
. Эта функция вызывает vkQueuePresentKHR()
от имени вашей игры.
Уничтожить цепочку обмена
Чтобы уничтожить данные SwappyVk
связанные с данной цепочкой обмена, выполните шаги, показанные в следующем фрагменте кода:
// Reusing local variables from previous snippets: // VkDevice device; // VkSwapchainKHR swapchain; // const VkAllocationCallbacks allocator; SwappyVk_destroySwapchain(device, swapchain); vkDestroySwapchainKHR(device, swapchain, &allocator);