使用以下函数将 Android Frame Pacing 与基于 Vulkan API 的渲染引擎结合使用。
确定创建实例所需的扩展
如需在使用 Vulkan 时收集创建 Android Frame Pacing 实例所需的扩展集,请完成以下代码段中所示的步骤:
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);
然后,您可以通过调用 vkCreateDevice()
启动 Android Frame Pacing。第二个参数(类型为 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);
定义交换链的帧速率
如需初始化指定物理设备和交换链的 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()
。如果您的 Android 显示 Surface 发生变化,并且您有新的 ANativeWindow
句柄,请调用 SwappyVk_setWindow()
(请参阅 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);