Vulkan प्री-रोटेशन की मदद से डिवाइस की स्क्रीन की दिशा मैनेज करें

इस लेख में डिवाइस को घुमाने के तरीके को बेहतर तरीके से मैनेज करने का तरीका बताया गया है अपने Vulkan ऐप्लिकेशन में, प्री-रोटेशन को लागू करके.

Vulkan की मदद से ये काम किए जा सकते हैं OpenGL के साथ रेंडर करने की स्थिति के बारे में ज़्यादा जानकारी देने के लिए. Vulkan के साथ, आपको उन चीज़ों को साफ़ तौर पर लागू करना होगा जिन्हें ड्राइवर मैनेज करता है OpenGL, जैसे कि डिवाइस ओरिएंटेशन और इसका संबंध रेंडर सरफ़ेस ओरिएंटेशन. Android, तीन तरीकों से डिवाइस की रेंडर सतह का मिलान डिवाइस ओरिएंटेशन के साथ करने को हैंडल करें:

  1. Android OS, डिवाइस की डिसप्ले प्रोसेसिंग यूनिट (डीपीयू) का इस्तेमाल कर सकता है, जो हार्डवेयर में सतह के घूमने को बेहतर तरीके से हैंडल कर सके. यहां उपलब्ध इस्तेमाल किया जा सकता है.
  2. Android OS, एक कंपोज़िटर पास जोड़कर सरफ़ेस रोटेशन को मैनेज कर सकता है. यह की परफ़ॉर्मेंस लागत इस बात पर निर्भर करेगी कि कंपोज़िटर को क्या करना है आउटपुट इमेज को घुमा रही हूँ.
  3. अनुप्रयोग खुद सतह के घुमाव को रेंडर कर सकता है चित्र को ऐसी रेंडर सतह पर घुमाई गई जो इसके वर्तमान अभिविन् यास से मेल खाता है डिसप्ले.

आपको इनमें से किस तरीके का इस्तेमाल करना चाहिए?

फ़िलहाल, किसी ऐप्लिकेशन के पास यह जानने का कोई तरीका नहीं है कि सरफ़ेस रोटेशन ऐप्लिकेशन के बाहर मैनेज करना मुफ़्त होगा. भले ही, DPU की मदद लेने के लिए नहीं रखने पर भी, परफ़ॉर्मेंस पर काफ़ी जुर्माना लगाया जा सकता है. सबसे ज़्यादा इस्तेमाल होता है. अगर आपका ऐप्लिकेशन सीपीयू से जुड़ी है, तो इस वजह से पावर से जुड़ी समस्या हो सकती है Android Compositor ने जीपीयू के इस्तेमाल में बढ़ोतरी की है. आम तौर पर, बूस्ट किया गया फ़्रीक्वेंसी. अगर आपका ऐप्लिकेशन जीपीयू से जुड़ी है, तो Android कंपोज़िटर आपके ऐप्लिकेशन के जीपीयू काम को भी रोक सकता है, जिससे अतिरिक्त परफ़ॉर्मेंस नुकसान.

Pixel 4XL पर शिपिंग के टाइटल चलाते समय, हमने देखा है कि वह SurfaceFlinger (सबसे ज़्यादा प्राथमिकता वाला वह टास्क है जो Android को बेहतर बनाता है) कंपोज़िटर):

  • नियमित रूप से ऐप्लिकेशन के काम को पहले से ही पूरा करता है. इस वजह से, ऐप्लिकेशन के काम को 1 से 3 मि॰से॰ तक किया जा सकता है फ़्रेम टाइम तक हिट करता है, और

  • जीपीयू पर ज़्यादा दबाव पड़ता है वर्टेक्स/टेक्सचर मेमोरी, क्योंकि कंपोज़िटर को पूरा फ़्रेम बफ़र का इस्तेमाल किया जा सकता है.

हैंडलिंग ओरिएंटेशन को ठीक से मैनेज करने से, SurfaceFlinger में जीपीयू से मिलने वाली वैल्यू को रोका जाता है पूरी तरह से, जबकि बूस्ट की गई फ़्रीक्वेंसी की वजह से जीपीयू की फ़्रीक्वेंसी 40% कम हो जाती है Android कंपोज़िटर की अब ज़रूरत नहीं है.

यह पक्का करने के लिए कि सतह के घूमने को उतना ही छोटा ओवरहेड सही तरीके से हैंडल किया जाए जैसा कि ऊपर दिए गए मामले में देखा जा सकता है, आपको तीसरा तरीका लागू करना चाहिए. इसे प्री-रोटेशन के नाम से जाना जाता है. इससे Android OS को पता चलता है कि आपका ऐप्लिकेशन यह सरफ़ेस रोटेशन का इस्तेमाल करता है. ऐसा करने के लिए, सरफ़ेस ट्रांसफ़ॉर्म फ़्लैग पास करें जो स्वैपचेन बनाते समय ओरिएंटेशन के बारे में जानकारी देते हैं. इससे मेरी साइट रुक जाती है Android कंपोज़िटर को खुद रोटेशन करने से रोकना.

Vulkan के लिए, सरफ़ेस ट्रांसफ़ॉर्म फ़्लैग सेट करने का तरीका जानना ज़रूरी है का इस्तेमाल करें. ऐप्लिकेशन अक्सर एक से ज़्यादा ओरिएंटेशन (स्क्रीन की दिशा) में काम करते हैं या ऐसे सिंगल ओरिएंटेशन का इस्तेमाल किया जा सकता है जहां रेंडर सरफ़ेस अलग स्क्रीन की दिशा उस हिसाब से तय करें जिसे डिवाइस अपने आइडेंटिटी ओरिएंटेशन के हिसाब से मानता है. उदाहरण के लिए, पोर्ट्रेट-आइडेंटिटी फ़ोन पर सिर्फ़ लैंडस्केप ऐप्लिकेशन या सिर्फ़ पोर्ट्रेट मोड में ऐप्लिकेशन लैंडस्केप-आइडेंटिटी टैबलेट पर एक ऐप्लिकेशन है.

AndroidManifest.xml में बदलाव करें

अपने ऐप्लिकेशन में डिवाइस का रोटेशन मैनेज करने के लिए, ऐप्लिकेशन की AndroidManifest.xml फ़ाइल, जिससे Android को पता चलता है कि आपका ऐप्लिकेशन स्क्रीन की दिशा (ओरिएंटेशन) को हैंडल करेगा साथ ही, स्क्रीन साइज़ में बदलाव होता है. यह Android को बंद करने और फिर से बनाने से रोकता है Android Activity और onDestroy() फ़ंक्शन का इस्तेमाल अभिविन् यास में बदलाव होने पर मौजूदा विंडो की सतह. ऐसा करने के लिए एपीआई लेवल <13 के साथ काम करने के लिए, orientation और screenSize एट्रिब्यूट जोड़ना गतिविधि के configChanges सेक्शन:

<activity android:name="android.app.NativeActivity"
          android:configChanges="orientation|screenSize">

अगर आपका ऐप्लिकेशन screenOrientation का इस्तेमाल करके, अपना स्क्रीन ओरिएंटेशन ठीक करता है विशेषता के लिए कुछ जोड़ना है, तो आपको यह करने की ज़रूरत नहीं है. साथ ही, अगर आपका ऐप्लिकेशन तो इसे स्वैपचेन को सिर्फ़ एक बार सेट अप करना होगा ऐप्लिकेशन स्टार्टअप/फिर से शुरू करें.

पहचान स्क्रीन रिज़ॉल्यूशन और कैमरा पैरामीटर पाएं

इसके बाद, डिवाइस के स्क्रीन रिज़ॉल्यूशन का पता लगाएं VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR वैल्यू से जुड़ा हुआ है. यह रिज़ॉल्यूशन, डिवाइस के आइडेंटिटी ओरिएंटेशन से जुड़ा होता है. साथ ही, इसलिए, यह ज़रूरी है कि स्वैपचेन को हमेशा सेट किया जाए. सबसे ज़्यादा भरोसेमंद तरीका है कि आप हमें कॉल करें. ऐप्लिकेशन शुरू होने पर vkGetPhysicalDeviceSurfaceCapabilitiesKHR(), और दिखाई गई सीमा को सेव करता है. इसके आधार पर चौड़ाई और ऊंचाई स्वैप करें currentTransform को यह पक्का करने के लिए भी लौटाया जाता है कि आप संग्रहित कर रहे हैं आइडेंटिटी स्क्रीन रिज़ॉल्यूशन:

VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevice, surface, &capabilities);

uint32_t width = capabilities.currentExtent.width;
uint32_t height = capabilities.currentExtent.height;
if (capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR ||
    capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
  // Swap to get identity width and height
  capabilities.currentExtent.height = width;
  capabilities.currentExtent.width = height;
}

displaySizeIdentity = capabilities.currentExtent;

DisplaySizeIdentity एक VkExtent2D स्ट्रक्चर है. इसका इस्तेमाल हम उस पहचान को सेव करने के लिए करते हैं ऐप्लिकेशन की विंडो की सतह का रिज़ॉल्यूशन, डिसप्ले के नैचुरल ओरिएंटेशन में हो.

डिवाइस के ओरिएंटेशन में बदलावों का पता लगाना (Android 10 और उसके बाद वाले वर्शन के लिए)

अपने ऐप्लिकेशन के ओरिएंटेशन में बदलाव का पता लगाने का सबसे भरोसेमंद तरीका है यह पुष्टि करने के लिए कि vkQueuePresentKHR() फ़ंक्शन लौटाता है या नहीं VK_SUBOPTIMAL_KHR. उदाहरण के लिए:

auto res = vkQueuePresentKHR(queue_, &present_info);
if (res == VK_SUBOPTIMAL_KHR){
  orientationChanged = true;
}

ध्यान दें: यह समाधान सिर्फ़ उन डिवाइसों पर काम करता है जिन पर यह सुविधा काम करती है Android 10 और उसके बाद के वर्शन. Android के ये वर्शन वापस आ गए हैं vkQueuePresentKHR() से VK_SUBOPTIMAL_KHR. हम इस समीक्षा के नतीजे को सेव करते हैं orientationChanged चेक इन करें, जो कि boolean ऐप्लिकेशन की मुख्य रेंडरिंग लूप.

डिवाइस के ओरिएंटेशन में हुए बदलावों का पता लगाना (Android 10 से पहले के वर्शन)

Android 10 या उससे पहले के वर्शन वाले डिवाइसों के लिए, लागू करना ज़रूरी है, क्योंकि VK_SUBOPTIMAL_KHR के साथ यह सुविधा काम नहीं करती.

पोल का इस्तेमाल करना

Android 10 से पहले के डिवाइसों पर, मौजूदा डिवाइस को pollingInterval फ़्रेम, जहां pollingInterval जानकारी का एक ऐसा लेवल है जिस पर का इस्तेमाल किया जा सकता है. ऐसा करने के लिए, vkGetPhysicalDeviceSurfaceCapabilitiesKHR() और फिर लौटाए गए प्रॉडक्ट की तुलना करना मौजूदा सेव किए गए सरफ़ेस में मौजूद currentTransform फ़ील्ड ट्रांसफ़ॉर्मेशन (इस कोड का उदाहरण, pretransformFlag में स्टोर किया गया है).

currFrameCount++;
if (currFrameCount >= pollInterval){
  VkSurfaceCapabilitiesKHR capabilities;
  vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevice, surface, &capabilities);

  if (pretransformFlag != capabilities.currentTransform) {
    window_resized = true;
  }
  currFrameCount = 0;
}

Android 10 वाले Pixel 4 पर, पोलिंग vkGetPhysicalDeviceSurfaceCapabilitiesKHR() ने .120-.250 मि॰से॰ और Android 8 वर्शन पर चलने वाले Pixel 1XL के साथ, पोलिंग में .110-.350 मि॰से॰ का समय लगा.

कॉलबैक का इस्तेमाल करना

Android 10 से पहले के वर्शन वाले डिवाइसों के लिए, दूसरा विकल्प यह है कि onNativeWindowResized() कॉलबैक करके, उस फ़ंक्शन को कॉल करें जो orientationChanged फ़्लैग, ऐप्लिकेशन को स्क्रीन की दिशा में बदलाव करने का संकेत देता है आया है:

void android_main(struct android_app *app) {
  ...
  app->activity->callbacks->onNativeWindowResized = ResizeCallback;
}

जहां ResizeCallback को इस तरह से परिभाषित किया गया है:

void ResizeCallback(ANativeActivity *activity, ANativeWindow *window){
  orientationChanged = true;
}

इस समाधान में समस्या यह है कि onNativeWindowResized() को सिर्फ़ जिसमें 90-डिग्री ओरिएंटेशन में बदलाव करने के लिए कहा गया हो, जैसे कि लैंडस्केप से पोर्ट्रेट या इसके साथ काम करता है. ओरिएंटेशन में अन्य बदलाव, स्वैपचेन मनोरंजन की सुविधा को ट्रिगर नहीं करेंगे. उदाहरण के लिए, लैंडस्केप से रिवर्स लैंडस्केप में बदलाव करने पर इसे ट्रिगर नहीं करता है, तो Android कंपोज़िटर को आपके डिवाइस के लिए फ़्लिप करने की ज़रूरत होती है का इस्तेमाल करें.

ओरिएंटेशन में बदलाव को मैनेज करना

स्क्रीन की दिशा में बदलाव को हैंडल करने के लिए, ओरिएंटेशन बदलने वाले रूटीन को इस नंबर पर कॉल करें जब orientationChanged वैरिएबल को 'सही' पर सेट किया गया है. उदाहरण के लिए:

bool VulkanDrawFrame() {
 if (orientationChanged) {
   OnOrientationChange();
}

आप स्वैपचेन को फिर से बनाने के लिए सभी ज़रूरी काम करते हैं OnOrientationChange() फ़ंक्शन. इसका मतलब है कि:

  1. Framebuffer और ImageView के किसी भी मौजूदा इंस्टेंस को खत्म करें,

  2. तबाही के साथ, स्वैपचेन को फिर से बनाएं पुरानी स्वैपचेन (जिसके बारे में आगे चर्चा की जाएगी) और

  3. नई स्वैप चेन की DisplayImage की मदद से फ़्रेमबफ़र फिर से बनाएं. ध्यान दें: अटैच की गई इमेज (उदाहरण के लिए, गहराई या स्टेंसिल वाली इमेज) आम तौर पर उन्हें नए सिरे से बनाने की ज़रूरत होती है. इमेज, पहले से घुमाई गई स्वैपचेन इमेज के आइडेंटिटी रिज़ॉल्यूशन पर आधारित होती हैं.

void OnOrientationChange() {
 vkDeviceWaitIdle(getDevice());

 for (int i = 0; i < getSwapchainLength(); ++i) {
   vkDestroyImageView(getDevice(), displayViews_[i], nullptr);
   vkDestroyFramebuffer(getDevice(), framebuffers_[i], nullptr);
 }

 createSwapChain(getSwapchain());
 createFrameBuffers(render_pass, depthBuffer.image_view);
 orientationChanged = false;
}

साथ ही, फ़ंक्शन के आखिर में आपने orientationChanged फ़्लैग को false पर रीसेट किया हो ताकि यह दिखाया जा सके कि आपने ओरिएंटेशन में बदलाव कर लिया है.

स्वैपचेन रीक्रिएशन

पिछले सेक्शन में, हमने स्वैपचेन टेक्नोलॉजी को फिर से बनाने के बारे में बताया है. ऐसा करने के लिए पहले कदम में, नई विशेषताओं को जानना शामिल होगा. रेंडरिंग प्लैटफ़ॉर्म:

void createSwapChain(VkSwapchainKHR oldSwapchain) {
   VkSurfaceCapabilitiesKHR capabilities;
   vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDevice, surface, &capabilities);
   pretransformFlag = capabilities.currentTransform;

VkSurfaceCapabilities स्ट्रक्चर में नई जानकारी डालने पर, आपको अब ओरिएंटेशन में बदलाव हुआ है या नहीं, यह देखने के लिए currentTransform फ़ील्ड. इसे pretransformFlag में बाद के लिए सेव किया जाएगा आपको इसकी ज़रूरत बाद में पड़ सकती है, क्योंकि आपको इसकी ज़रूरत तब पड़ती है, जब आप MVP मैट्रिक्स.

ऐसा करने के लिए, इन एट्रिब्यूट की वैल्यू डालें VkSwapchainCreateInfo स्ट्रक्चर में:

VkSwapchainCreateInfoKHR swapchainCreateInfo{
  ...
  .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
  .imageExtent = displaySizeIdentity,
  .preTransform = pretransformFlag,
  .oldSwapchain = oldSwapchain,
};

vkCreateSwapchainKHR(device_, &swapchainCreateInfo, nullptr, &swapchain_));

if (oldSwapchain != VK_NULL_HANDLE) {
  vkDestroySwapchainKHR(device_, oldSwapchain, nullptr);
}

imageExtent फ़ील्ड में, displaySizeIdentity की सीमा के हिसाब से अपने-आप जानकारी भर जाएगी जिन्हें आपने ऐप्लिकेशन स्टार्टअप पर सेव किया था. preTransform फ़ील्ड में जानकारी अपने-आप भर जाएगी के साथ pretransformFlag वैरिएबल (जो मौजूदा रूपांतरण फ़ील्ड पर सेट है) surfaceCapabilities में से). आपने oldSwapchain फ़ील्ड को तबाह हो जाएगा.

एमवीपी मैट्रिक्स अडजस्टमेंट

आखिर में आपको, बदलाव से पहले की प्रोसेस को लागू करना होगा अपने MVP मैट्रिक्स में रोटेशन मैट्रिक्स लागू करके. यह ज़रूरी तौर पर यह करता है कि रोटेशन को क्लिप स्पेस में लागू करें, ताकि इससे बनने वाली इमेज को मौजूदा डिवाइस ओरिएंटेशन. इसके बाद, अपडेट किए गए MVP मैट्रिक्स को पास किया जा सकता है अपने वर्टेक्स शेडर में डालें और इसे सामान्य तरीके से इस्तेमाल करें. शेडर.

glm::mat4 pre_rotate_mat = glm::mat4(1.0f);
glm::vec3 rotation_axis = glm::vec3(0.0f, 0.0f, 1.0f);

if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
  pre_rotate_mat = glm::rotate(pre_rotate_mat, glm::radians(90.0f), rotation_axis);
}

else if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
  pre_rotate_mat = glm::rotate(pre_rotate_mat, glm::radians(270.0f), rotation_axis);
}

else if (pretransformFlag & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
  pre_rotate_mat = glm::rotate(pre_rotate_mat, glm::radians(180.0f), rotation_axis);
}

MVP = pre_rotate_mat * MVP;

विचार - नॉन-फ़ुल स्क्रीन व्यूपोर्ट और सिज़र

अगर आपका ऐप्लिकेशन ऐसे व्यूपोर्ट/सिज़र क्षेत्र का इस्तेमाल कर रहा है जो फ़ुल स्क्रीन में नहीं है, तो को डिवाइस के ओरिएंटेशन के हिसाब से अपडेट करना होगा. यह यह ज़रूरी है कि आप Vulkan के डाइनैमिक व्यूपोर्ट और सिज़र विकल्प चालू करें पाइपलाइन बनाना:

VkDynamicState dynamicStates[2] = {
  VK_DYNAMIC_STATE_VIEWPORT,
  VK_DYNAMIC_STATE_SCISSOR,
};

VkPipelineDynamicStateCreateInfo dynamicInfo = {
  .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
  .pNext = nullptr,
  .flags = 0,
  .dynamicStateCount = 2,
  .pDynamicStates = dynamicStates,
};

VkGraphicsPipelineCreateInfo pipelineCreateInfo = {
  .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
  ...
  .pDynamicState = &dynamicInfo,
  ...
};

VkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &mPipeline);

निर्देश बफ़र रिकॉर्डिंग के दौरान व्यूपोर्ट की सीमा का असल हिसाब इस तरह लगाया जाता है:

int x = 0, y = 0, w = 500, h = 400;

glm::vec4 viewportData;

switch (device->GetPretransformFlag()) {
  case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
    viewportData = {bufferWidth - h - y, x, h, w};
    break;
  case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
    viewportData = {bufferWidth - w - x, bufferHeight - h - y, w, h};
    break;
  case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
    viewportData = {y, bufferHeight - w - x, h, w};
    break;
  default:
    viewportData = {x, y, w, h};
    break;
}

const VkViewport viewport = {
    .x = viewportData.x,
    .y = viewportData.y,
    .width = viewportData.z,
    .height = viewportData.w,
    .minDepth = 0.0F,
    .maxDepth = 1.0F,
};

vkCmdSetViewport(renderer->GetCurrentCommandBuffer(), 0, 1, &viewport);

x और y वैरिएबल व्यूपोर्ट की चौड़ाई और ऊंचाई की वैल्यू के तौर पर w और h का इस्तेमाल किया जाता है. कैंची टेस्ट को सेट करने के लिए भी इसी कंप्यूटेशन का इस्तेमाल किया जा सकता है. साथ ही, इसमें यह भी शामिल है पूरा जानने के लिए यहां देखें:

int x = 0, y = 0, w = 500, h = 400;
glm::vec4 scissorData;

switch (device->GetPretransformFlag()) {
  case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
    scissorData = {bufferWidth - h - y, x, h, w};
    break;
  case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
    scissorData = {bufferWidth - w - x, bufferHeight - h - y, w, h};
    break;
  case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
    scissorData = {y, bufferHeight - w - x, h, w};
    break;
  default:
    scissorData = {x, y, w, h};
    break;
}

const VkRect2D scissor = {
    .offset =
        {
            .x = (int32_t)viewportData.x,
            .y = (int32_t)viewportData.y,
        },
    .extent =
        {
            .width = (uint32_t)viewportData.z,
            .height = (uint32_t)viewportData.w,
        },
};

vkCmdSetScissor(renderer->GetCurrentCommandBuffer(), 0, 1, &scissor);

विचार - फ़्रैगमेंट शेडर डेरिवेटिव

अगर आपका ऐप्लिकेशन dFdx और dFdy जैसे डेरिवेटिव कंप्यूटेशन का इस्तेमाल करता है, तो घुमाए गए निर्देशांक के लिए, अतिरिक्त बदलावों की ज़रूरत पड़ सकती है सिस्टम इस तरह काम करता है कि ये कंप्यूटेशन (हिसाब लगाना) पिक्सल स्पेस में किए जाते हैं. इसके लिए ऐप्लिकेशन की ज़रूरत है प्रीट्रांसफ़ॉर्म के कुछ संकेत को फ़्रैगमेंट शेडर में पास करने के लिए (जैसे कि पूर्णांक) और उसका इस्तेमाल, डेरिवेटिव कंप्यूटेशन (डेरिवेटिव कंप्यूटेशन) सही तरीके से:

  • 90 डिग्री पहले से घुमाए गए फ़्रेम के लिए
    • dFdx को dFdy पर मैप किया जाना चाहिए
    • dFdy को -dFdx पर मैप किया जाना चाहिए
  • 270 डिग्री पहले से घुमाए गए फ़्रेम के लिए
    • dFdx को -dFdy पर मैप किया जाना चाहिए
    • dFdy को dFdx पर मैप किया जाना चाहिए
  • 180 डिग्री पहले से घुमाए गए फ़्रेम के लिए,
    • dFdx को -dFdx पर मैप किया जाना चाहिए
    • dFdy को -dFdy पर मैप किया जाना चाहिए

नतीजा

आपके ऐप्लिकेशन के ज़रिए, Android पर Vulkan का ज़्यादा से ज़्यादा फ़ायदा पाने के लिए, प्री-रोटेशन को लागू करना ज़रूरी है. इससे सबसे ज़रूरी सीख लेख हैं:

  • यह पक्का करें कि स्वैपचेन बनाने या मनोरंजन के दौरान, प्रीट्रांसफ़ॉर्म फ़्लैग का मिलान Android ऑपरेटिंग सिस्टम से मिले फ़्लैग से मेल खाने के लिए किया जा सकता है. इससे, कंपोज़िटर ओवरहेड.
  • स्वैपचेन साइज़ को ऐप्लिकेशन की विंडो के आइडेंटिटी रिज़ॉल्यूशन तक ही रखें स्क्रीन के नैचुरल ओरिएंटेशन वाले हिस्से को हाइलाइट करें.
  • डिवाइस की स्क्रीन की दिशा के हिसाब से, एमवीपी मैट्रिक्स को क्लिप वाली जगह में घुमाएं, क्योंकि स्वैपचेन रिज़ॉल्यूशन/एक्सटेंट अब ओरिएंटेशन के साथ अपडेट नहीं होता डिसप्ले पर रखा जा सकता है.
  • अपने ऐप्लिकेशन के हिसाब से, व्यूपोर्ट और सिज़र रेक्टैंगल अपडेट करें.

ऐप्लिकेशन का सैंपल: Android का, पहले से ही अलग-अलग तरह से नेविगेट करने का कम से कम समय