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을 시작할 수 있습니다. 두 번째 인수인 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의 프레임 속도 정의
지정된 실제 기기 및 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 설정
ANativeWindow_setFrameRate()
호출과 같은 ANativeWindow
관련 작업을 실행하기 위해서는 Swappy에 ANativeWindow
핸들이 필요합니다.
Android 디스플레이 노출 영역이 변경되고 새로운 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()
을 호출합니다.
swapchain 소멸
특정 swapchain과 연결된 SwappyVk
데이터를 소멸하려면 다음 코드 스니펫에 나와 있는 단계를 완료하세요.
// Reusing local variables from previous snippets:
// VkDevice device;
// VkSwapchainKHR swapchain;
// const VkAllocationCallbacks allocator;
SwappyVk_destroySwapchain(device, swapchain);
vkDestroySwapchainKHR(device, swapchain, &allocator);