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