स्क्रिप्ट को OpenGL ES 3.1 पर माइग्रेट करें

ऐसे वर्कलोड के लिए जहां जीपीयू कंप्यूट का सबसे अच्छा तरीका अपनाया जाता है, तो RenderScript स्क्रिप्ट को OpenGL ES (जीएलईएस), Kotlin, Java में लिखे गए ऐप्लिकेशन या एनडीके का इस्तेमाल करने की अनुमति देता है जीपीयू हार्डवेयर का इस्तेमाल करें. OpenGL ES 3.1 कंप्यूट शेडर का इस्तेमाल करने में आपकी मदद करने के लिए, यहां दी गई खास जानकारी नीचे दी गई है RenderScript स्क्रिप्ट को बदलें.

जीएलईएस शुरू करना

RenderScript कॉन्टेक्स्ट ऑब्जेक्ट बनाने के बजाय, यह तरीका अपनाएं EGL का इस्तेमाल करके, जीएलईएस ऑफ़स्क्रीन कॉन्टेक्स्ट बनाने के लिए:

  1. डिफ़ॉल्ट डिसप्ले पाएं

  2. जीएलईएस वर्शन की जानकारी देते हुए, डिफ़ॉल्ट डिसप्ले का इस्तेमाल करके EGL शुरू करें.

  3. कोई EGL कॉन्फ़िगरेशन चुनें, जिसकी सतह का प्रकार EGL_PBUFFER_BIT.

  4. EGL संदर्भ बनाने के लिए डिसप्ले और कॉन्फ़िगरेशन का इस्तेमाल करें.

  5. इसकी मदद से ऑफ़स्क्रीन सरफ़ेस बनाएं eglCreatePBufferSurface. अगर कॉन्टेक्स्ट का इस्तेमाल सिर्फ़ कंप्यूट के लिए किया जाएगा. हालांकि, यह एक छोटा (1x1) की जगह है.

  6. रेंडर थ्रेड बनाएं और कॉल करें eglMakeCurrent है, जो रेंडर थ्रेड में डिसप्ले, सरफ़ेस, और ईजीएल कॉन्टेक्स्ट को थ्रेड से बाइंड किया जा सकेगा.

सैंपल ऐप्लिकेशन में, जीएलईएस कॉन्टेक्स्ट को शुरू करने का तरीका बताया गया है GLSLImageProcessor.kt. इस बारे में ज़्यादा जानने के लिए, यह देखें EGLSurfaces और OpenGL ES.

जीएलईएस डीबग आउटपुट

OpenGL से उपयोगी गड़बड़ियां पाने के लिए, डीबग लॉगिंग को चालू करने के लिए एक एक्सटेंशन का इस्तेमाल किया जाता है जो एक डीबग आउटपुट कॉलबैक सेट करता है. SDK टूल की मदद से यह काम करने का तरीका, glDebugMessageCallbackKHR को कभी भी लागू नहीं किया गया है. साथ ही, यह अपवाद. ऐप्लिकेशन का नमूना इसमें NDK कोड से कॉलबैक के लिए एक रैपर शामिल होता है.

जीएलईएस ऐलोकेशन

रेंडर स्क्रिप्ट ऐलोकेशन को अम्यूटेबल स्टोरेज टेक्स्चर या Shader स्टोरेज बफ़र ऑब्जेक्ट. सिर्फ़ पढ़ने की सुविधा वाली इमेज के लिए, आपको किसी सैंपलर ऑब्जेक्ट का इस्तेमाल कर सकता है, जिससे फ़िल्टर करना.

जीएलईएस संसाधनों का बंटवारा जीएलईएस के तहत किया जाता है. मेमोरी की कॉपी बनाने से बचने के लिए ओवरहेड, Android के अन्य कॉम्पोनेंट के साथ इंटरैक्ट करते समय KHR इमेज के लिए एक्सटेंशन है जो शेयर करने की अनुमति देता है 2D कलेक्शन हैं. Android डिवाइसों के लिए यह एक्सटेंशन ज़रूरी है Android 8.0 से शुरू होता है. कॉन्टेंट बनाने ग्राफ़िक्स-कोर Android Jetpack लाइब्रेरी में इन इमेज को बनाने के लिए, मैनेज किए जा रहे कोड और मैपिंग की मदद शामिल है उन्हें असाइन किए गए HardwareBuffer में जोड़ दिया जाएगा:

val outputBuffers = Array(numberOfOutputImages) {
  HardwareBuffer.create(
    width, height, HardwareBuffer.RGBA_8888, 1,
    HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
  )
}
val outputEGLImages = Array(numberOfOutputImages) { i ->
    androidx.opengl.EGLExt.eglCreateImageFromHardwareBuffer(
        display,
        outputBuffers[i]
    )!!
}

माफ़ करें, इससे उपयोगकर्ताओं के लिए ज़रूरी स्टोरेज नहीं बनता यह एक कंप्यूट शेडर है, जो सीधे बफ़र में लिखने के लिए है. सैंपल, इस्तेमाल किए गए स्टोरेज टेक्स्चर को कॉपी करने के लिए glCopyTexSubImage2D को कंप्यूट शेडर से KHR Image में बदल दिया. अगर OpenGL ड्राइवर EGL Image Storage एक्सटेंशन, फिर वह एक्सटेंशन कॉपी से बचने के लिए, शेयर किया गया नहीं बदला जा सकने वाला स्टोरेज टेक्सचर बनाने के लिए इस्तेमाल किया जा सकता है.

जीएलएसएल कंप्यूट शेडर में बदलना

आपकी RenderScript स्क्रिप्ट, जीएलएसएल कंप्यूट शेडर में बदल दी गई है.

जीएलएसएल कंप्यूट शेडर लिखना

OpenGL ES में,कंप्यूट शेडर OpenGL शेडिंग लैंग्वेज (जीएलएसएल).

स्क्रिप्ट ग्लोबल का अडैप्टेशन

स्क्रिप्ट ग्लोबल की विशेषताओं के आधार पर, यूनिफ़ॉर्म का इस्तेमाल किया जा सकता है या ग्लोबल, जो शेडर में बदले नहीं गए हैं, के लिए यूनिफ़ॉर्म बफ़र ऑब्जेक्ट:

  • यूनिफ़ॉर्म बफ़र: अक्सर बदलने वाले स्क्रिप्ट ग्लोबल के लिए सुझाए गए साइज़ से बड़े साइज़ के कॉन्सटेंट लिमिट बढ़ाएं.

शेडर में बदले जाने वाले ग्लोबल के लिए, आप अम्यूटेबल स्टोरेज टेक्स्चर या Shader स्टोरेज बफ़र ऑब्जेक्ट.

कंप्यूटेशन चलाएं

कंप्यूट शेडर, ग्राफ़िक पाइपलाइन का हिस्सा नहीं हैं; इन टूल का इस्तेमाल अलग-अलग मकसद के लिए किया जाता है और साथ में काम करने लायक नौकरियों को कैलकुलेट करने के लिए डिज़ाइन किया गया है. इससे आपको और बेहतर तरीके से कंट्रोल करना मुमकिन है, लेकिन इसका मतलब यह भी है कि आपको आपका काम साथ-साथ कैसे आगे बढ़ता है.

कंप्यूट प्रोग्राम बनाना और शुरू करना

कंप्यूट प्रोग्राम को बनाने और उसे शुरू करने में, कई चीज़ें एक जैसी हैं किसी भी अन्य जीएलईएस शेडर के साथ काम करना.

  1. प्रोग्राम और उससे जुड़ा कंप्यूट शेडर बनाएं.

  2. शेडर सोर्स अटैच करें, शेडर को कंपाइल करें (और नतीजे देखें संग्रह में रखा है).

  3. शेडर अटैच करें, प्रोग्राम को लिंक करें, और प्रोग्राम का इस्तेमाल करें.

  4. कोई भी यूनिफ़ॉर्म बनाएं, शुरू करें, और बाइंड करें.

हिसाब लगाना शुरू करें

कंप्यूट शेडर किसी सीरीज़ पर ऐब्स्ट्रैक्ट 1D, 2D या 3D स्पेस में काम करते हैं वे वर्कग्रुप हैं जिन्हें शेडर सोर्स कोड में तय किया जाता है और न्योते का कम से कम साइज़ और शेडर की ज्यामिति. नीचे दिया गया शेडर 2D इमेज पर काम करता है और वर्क ग्रुप को दो इमेज में बांटता है डाइमेंशन:

private const val WORKGROUP_SIZE_X = 8
private const val WORKGROUP_SIZE_Y = 8
private const val ROTATION_MATRIX_SHADER =
    """#version 310 es
    layout (local_size_x = $WORKGROUP_SIZE_X, local_size_y = $WORKGROUP_SIZE_Y, local_size_z = 1) in;

वर्कग्रुप, GL_MAX_COMPUTE_SHARED_MEMORY_SIZE के हिसाब से तय की गई मेमोरी को शेयर कर सकते हैं, जो कम से कम 32 केबी का हो. साथ ही, इस डेटा को उपलब्ध कराने के लिए memoryBarrierShared() का इस्तेमाल किया जा सकता है आसानी से ऐक्सेस करने की सुविधा.

वर्कग्रुप का साइज़ तय करना

भले ही आपका प्रॉब्लम स्पेस 1 वाले वर्कग्रुप साइज़ के साथ ठीक से काम करता हो, लेकिन कंप्यूट शेडर को पैरलल करने के लिए, सही वर्कग्रुप का साइज़ ज़रूरी है. अगर साइज़ बहुत छोटा है, तो हो सकता है कि जीपीयू ड्राइवर आपके कंप्यूटेशन को साथ में न कर पाए काफ़ी हो जाता है. आम तौर पर, इन साइज़ को हर जीपीयू के हिसाब से ट्यून किया जाना चाहिए, हालांकि डिफ़ॉल्ट तौर पर सेट की गई डिफ़ॉल्ट सेटिंग, वर्कग्रुप जैसे मौजूदा डिवाइसों पर सही से काम करती है शेडर स्निपेट में 8x8 का साइज़ होता है.

वहां एक GL_MAX_COMPUTE_WORK_GROUP_COUNT है, लेकिन यह काफ़ी है; यह होना चाहिए दिए गए निर्देशों के हिसाब से, सभी तीनों ऐक्सिस में कम से कम 65535 हो.

शेडर भेजें

कंप्यूटेशन की प्रोसेस का आखिरी चरण, शेडर को एक कॉन्फ़िगरेशन का इस्तेमाल करके डिस्पैच करना है डिस्पैच फ़ंक्शन का इस्तेमाल करते हैं, जैसे कि glDispatchCompute. डिस्पैच फ़ंक्शन ज़िम्मेदार होता है हर ऐक्सिस के लिए, वर्कग्रुप की संख्या सेट करने के लिए:

GLES31.glDispatchCompute(
  roundUp(inputImage.width, WORKGROUP_SIZE_X),
  roundUp(inputImage.height, WORKGROUP_SIZE_Y),
  1 // Z workgroup size. 1 == only one z level, which indicates a 2D kernel
)

इस वैल्यू को वापस करने के लिए, कंप्यूट की कार्रवाई पूरी होने का इंतज़ार करें. इसके लिए, मेमोरी बैरियर:

GLES31.glMemoryBarrier(GLES31.GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)

कई कर्नेल को एक साथ जोड़ने के लिए, (उदाहरण के लिए, ScriptGroup का इस्तेमाल करके कोड माइग्रेट करने के लिए), बनाएं और भेजें कई प्रोग्राम हैं और आउटपुट में उनकी ऐक्सेस को मेमोरी के साथ सिंक करते हैं मुश्किलें हैं.

ऐप्लिकेशन का नमूना दो कंप्यूट टास्क दिखाता है:

  • HUE का रोटेशन: एक कंप्यूट शेडर वाला कंप्यूट टास्क. यहां जाएं: कोड सैंपल के लिए GLSLImageProcessor::rotateHue.
  • धुंधला करें: यह ज़्यादा जटिल कंप्यूट टास्क होता है, जो एक क्रम में दो कंप्यूट टास्क करता है शेडर. कोड सैंपल के लिए GLSLImageProcessor::blur देखें.

मेमोरी से जुड़ी समस्याओं के बारे में ज़्यादा जानने के लिए, यहां जाएं: प्रॉडक्ट दिख रहा है या नहीं और साथ ही शेयर किए गए वैरिएबल को अपनाएं.