نقل النصوص البرمجية إلى OpenGL ES 3.1

بالنسبة إلى مهام العمل التي يكون فيها الحوسبة على وحدة معالجة الرسومات مثاليًا، يجب نقل نصوص RenderScript إلى يسمح OpenGL ES (GLES) بالتطبيقات المكتوبة بلغة Kotlin أو Java أو التي تستخدم NDK للاستفادة من أجهزة وحدة معالجة الرسومات. في ما يلي نظرة عامة عالية المستوى لمساعدتك في استخدام أدوات تظليل OpenGL ES 3.1 على الكمبيوتر استبدال نصوص RenderScript البرمجية.

إعداد GLES

بدلاً من إنشاء كائن سياق RenderScript، نفِّذ الخطوات التالية. لإنشاء سياق خارج الشاشة GLES باستخدام EGL:

  1. الحصول على شاشة العرض التلقائية

  2. قم بتهيئة EGL باستخدام العرض الافتراضي، مع تحديد إصدار GLES.

  3. اختر تهيئة EGL بنوع سطح EGL_PBUFFER_BIT

  4. استخدم العرض والتهيئة لإنشاء سياق EGL.

  5. يمكنك إنشاء السطح خارج الشاشة باستخدام eglCreatePBufferSurface إذا لم يكن السياق سيتم استخدامه فقط في الحوسبة، وقد يكون هذا النموذج صغيرًا بشكل بسيط (1×1) السطح.

  6. إنشاء سلسلة محادثات العرض وطلب eglMakeCurrent في سلسلة العرض التي تتضمّن كلاً من الشاشة وسطحه وسياق EGL لربط سياق GL بمؤشر الترابط.

يوضح نموذج التطبيق كيفية تهيئة سياق GLES في GLSLImageProcessor.kt لمزيد من المعلومات، يُرجى مراجعة EGLSurfaces وOpenGL ES:

نتيجة تصحيح الأخطاء في GLES

يؤدي الحصول على أخطاء مفيدة من OpenGL إلى استخدام إضافة لتفعيل تسجيل تصحيح الأخطاء. تعيّن استدعاءً ناتجًا لتصحيح الأخطاء. طريقة القيام بذلك من خلال SDK، glDebugMessageCallbackKHR، لم يتم تنفيذه مطلقًا، ويعرض استثناء. نموذج التطبيق يتضمن برنامج تضمين لمعاودة الاتصال من رمز NDK.

توزيعات GLES

يمكن نقل تخصيص RenderScript إلى زخرفة تخزين غير قابلة للتغيير أو كائن التخزين المؤقت في Shader. بالنسبة إلى الصور المتوفرة للقراءة فقط، يجب استخدام كائن عيّنات، ما يسمح والتصفية.

يتم تخصيص موارد GLES ضمن GLES. لتجنب نسخ الذاكرة البيانات العامة عند التفاعل مع مكونات Android الأخرى، لصور KHR التي تتيح مشاركة صفائف بيانات الصورة ثنائية الأبعاد. هذه الإضافة مطلوبة لأجهزة 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، ثم تلك الإضافة استخدامها لإنشاء زخرفة تخزين مشتركة غير قابلة للتغيير لتجنب النسخة.

التحويل إلى أدوات تظليل الحوسبة في GLSL

يتم تحويل نصوص RenderScript إلى أدوات تظليل الحوسبة في GLSL.

كتابة أداة تظليل الحوسبة GLSL

في OpenGL ES، تتم كتابة أدوات تظليل الحوسبة في لغة تظليل OpenGL (GLSL).

تكييف البرنامج النصي

بناءً على خصائص النص العالمي، يمكنك إما استخدام الزي الرسمي أو كائنات المخزن المؤقت المنتظمة للعمومات التي لا يتم تعديلها في أداة التظليل:

بالنسبة إلى المتغيرات العمومية التي يتم تغييرها داخل أداة التظليل، يمكنك استخدام زخرفة تخزين غير قابلة للتغيير أو كائن التخزين المؤقت في Shader.

تنفيذ العمليات الحسابية

لا تشكّل أدوات تظليل الحوسبة جزءًا من مسار الرسومات، هي الأغراض العامة ومصممة لحساب الوظائف القابلة للقياس بشكل كبير. يتيح لك هذا مزيدًا من التحكم في كيفية تنفيذها، ولكنه يعني أيضًا أنه يجب عليك لفهم المزيد عن كيفية توازي عملك.

إنشاء برنامج الحوسبة وتهيئته

هناك الكثير من القواسم المشتركة بين إنشاء برنامج الحوسبة وتهيئته والعمل مع أي أداة تظليل GLES.

  1. أنشِئ البرنامج وأداة تظليل الحوسبة المرتبطة به.

  2. أرفِق مصدر أداة التظليل، وجمِّع أداة التظليل (واطّلِع على النتائج) التجميع).

  3. أرفِق أداة التظليل واربط البرنامج واستخدِم البرنامج.

  4. إنشاء أي أزياء موحدة وإعدادها وربطها.

بدء حوسبة

تعمل أدوات تظليل الحوسبة ضمن مساحة مجردة أحادية الأبعاد أو ثنائية الأبعاد أو ثلاثية الأبعاد في سلسلة ما. من مجموعات العمل، التي يتم تحديدها ضمن رمز مصدر أداة التظليل، وتمثل الحد الأدنى لحجم الاستدعاء بالإضافة إلى هندسة أداة التظليل. تعمل أداة التظليل التالية على صورة ثنائية الأبعاد وتحدد مجموعات العمل في الأبعاد:

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، فإن تعيين أمرًا مهمًا لموازاة أداة تظليل الحوسبة. إذا كان الحجم صغيرًا جدًا، فقد لا يكون برنامج تشغيل وحدة معالجة الرسومات موازٍ لعملية الحوسبة. بما يكفي، على سبيل المثال. من الناحية المثالية، يجب ضبط هذه الأحجام لكل وحدة معالجة رسومات، على الرغم من تعمل الإعدادات الافتراضية المعقولة بشكل جيد على نحو كافٍ على الأجهزة الحالية، مثل مجموعة العمل بحجم 8×8 في مقتطف أداة التظليل.

هناك 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)، وإنشاء وإرسال برامج متعددة ومزامنة وصولها إلى المخرجات مع البيانات حواجز.

نموذج التطبيق يوضح مهمتي حوسبة:

  • تدوير تدرج اللون: مهمة حوسبة باستخدام أداة تظليل حوسبة واحدة. عرض GLSLImageProcessor::rotateHue لنموذج الرمز البرمجي
  • التمويه: مهمة حوسبة أكثر تعقيدًا تنفذ عمليتَي حوسبة بالتسلسل أدوات تظليل. يمكنك الانتقال إلى GLSLImageProcessor::blur للاطّلاع على نموذج الرمز البرمجي.

لمزيد من المعلومات حول حواجز الذاكرة، يمكنك الرجوع إلى ضمان ظهور المحتوى وكذلك المتغيّرات المشتركة .