フレーム ペーシング関数の追加

Vulkan API ベースのレンダリング エンジンで Android Frame Pacing を使用するには、以下の関数を使います。

作成に必要な拡張機能を特定する

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 を開始できます。その際の 2 番目の引数である VkDeviceCreateInfo* 型の構造体の enabledExtensionCount メンバーに、必要な拡張機能の数を設定する必要があります。

キュー ファミリーを特定する

正しいディスプレイ キューを提示するためには、Vulkan が使用しているキュー ファミリーを Android Frame Pacing が認識している必要があります。正しいファミリーを決定するには、次のコード スニペットに示す手順を行います。

// 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_setFrameRate() の呼び出しなどの ANativeWindow 固有のオペレーションを実行するために ANativeWindow のハンドルが必要です。Android ディスプレイ サーフェスが変更され、ANativeWindow ハンドルが新しくなったときに SwappyVk_setWindow() を呼び出します(例として Cube サンプルをご覧ください)。

自動モード

Android Frame Pacing は、前のフレームの平均時間に基づいてスワップ時間とパイプライン モードを調整します。この動作は、次の関数を使用して制御できます。

フレームを提示する

ゲームのフレームを 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);