Adicionar funções de ritmo de frame

Use as funções a seguir para usar o Android Frame Pacing com um mecanismo de renderização baseado na API Vulkan.

Identificar as extensões necessárias para a criação

Para coletar o conjunto de extensões necessárias para criar uma instância do Android Frame Pacing ao usar Vulkan, siga as etapas apresentadas no seguinte snippet de código:

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);

Em seguida, você pode iniciar o Android Frame Pacing chamando vkCreateDevice(). O segundo argumento, uma estrutura do tipo VkDeviceCreateInfo*, precisa ter o membro enabledExtensionCount definido como o número de extensões necessárias.

Identificar família de filas

Para apresentar a fila de exibição correta, o Android Frame Pacing precisa saber qual família de filas o Vulkan está usando. Para determinar a família correta, siga as etapas apresentadas neste snippet de código:

// 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);

Definir frame rate para cadeia de troca

Para inicializar o Android Frame Pacing para um dispositivo físico e uma cadeia de troca específicos, siga as etapas apresentadas neste snippet de código:

// 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);

Isso determina a duração da troca em nanossegundos. Há macros auxiliares definidas em swappy_common.h para durações de troca comuns (por exemplo, SWAPPY_SWAP_60FPS).

Em seguida, informe a duração da troca em nanossegundos.

// 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);

Configuração do ANativeWindoW

O Swappy precisa do handle de ANativeWindow para executar uma operação específica de ANativeWindow, como chamar ANativeWindow_setFrameRate(). Chame SwappyVk_setWindow() quando a superfície de exibição do Android mudar e você tiver um novo identificador ANativeWindow (consulte a amostra do Cube para ver um exemplo).

Modos automáticos

A Android Frame Pacing ajusta a duração da troca e o modo do pipeline com base na duração média dos frames anteriores. É possível controlar esse comportamento com as seguintes funções:

Apresentar um frame

Para apresentar um frame do seu jogo à Android Frame Pacing, chame SwappyVk_queuePresent(). Essa função chama vkQueuePresentKHR() em nome do jogo.

Destruir a cadeia de troca

Para destruir os dados SwappyVk associados a determinada cadeia de troca, siga as etapas apresentadas neste snippet de código:

// Reusing local variables from previous snippets:
// VkDevice device;
// VkSwapchainKHR swapchain;
// const VkAllocationCallbacks allocator;

SwappyVk_destroySwapchain(device, swapchain);
vkDestroySwapchainKHR(device, swapchain, &allocator);