הוספת פונקציות של קצב ניצול הפריימים

אפשר להשתמש בפונקציות הבאות כדי להשתמש ב-Android Frame Pacing עם מנוע רינדור שמבוסס על Vulkan API.

זיהוי התוספים הנדרשים ליצירה

כדי לאסוף את קבוצת התוספים שנדרשים ליצירת מופע של Android Frame Pacing כשמשתמשים ב-Vulkan, מבצעים את השלבים שמוצגים בקטע הקוד הבא:

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

אחרי כן אפשר להתחיל את Android Frame Pacing על ידי קריאה ל-vkCreateDevice(). הארגומנט השני, מבנה מסוג 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

כדי לאתחל את Android Frame Pacing עבור מכשיר פיזי ו-swapchain נתונים, צריך לבצע את השלבים שמוצגים בקטע הקוד הבא:

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

ההגדרה הזו קובעת את משך ההחלפה בננו-שניות. יש פקודות מאקרו מסוג helper שמוגדרות ב-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(). ‫Call SwappyVk_setWindow() כשמשטח התצוגה של Android משתנה ויש לכם ANativeWindow handle חדש (אפשר לראות דוגמה בדוגמה של Cube).

מצבים אוטומטיים

ב-Android, התכונה 'התאמת קצב הפריימים' משנה את משך ההחלפה ואת מצב צינור העיבוד על סמך משך הזמן הממוצע של הפריימים הקודמים. אפשר לשלוט בהתנהגות הזו באמצעות הפונקציות הבאות:

הצגת מסגרת

כדי להציג פריים של המשחק ב-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);