برامج تظليل Vulkan على Android

يجب أن يدير تطبيق Vulkan أدوات التظليل بشكل مختلف عن طريقة إدارة تطبيق OpenGL ES: في OpenGL ES، توفر أداة تظليل كمجموعة من السلاسل التي تشكل النص المصدر لبرنامج التظليل من خلال GLSL. على النقيض من ذلك، تتطلب منك واجهة برمجة التطبيقات Vulkan توفير أداة تظليل في شكل نقطة دخول في وحدة SPIR-V.

يتضمّن الإصدار 12 من NDK والإصدارات الأحدث مكتبة وقت تشغيل لتجميع GLSL إلى SPIR-V. إنّ مكتبة وقت التشغيل هي نفسها تلك المتوفرة في مشروع Shaderc المفتوح المصدر، وتستخدم المحول البرمجي المرجعي نفسه في Glslang GLSL كواجهة خلفية. بشكل افتراضي، يفترض إصدار Shaderc من المحوّل أنك تجري التحويل لـ Vulkan. بعد التحقّق ممّا إذا كان الرمز صالحًا للاستخدام على Vulkan، يعمل برنامج التجميع تلقائيًا على تفعيل إضافة KHR_vulkan_glsl. وينشئ إصدار Shaderc من المحول البرمجي أيضًا رمز SPIR-V متوافق مع Vulkan.

يمكنك اختيار تجميع وحدات SPIR-V في تطبيق Vulkan أثناء عملية التطوير، وهي ممارسة تُسمّى ahead oftime أو AOT. بدلاً من ذلك، يمكنك أن تطلب من تطبيقك تجميعها من مصدر تظليل تم شحنه أو إنشاؤه بشكل إجرائي عند الحاجة أثناء وقت التشغيل. وتُسمى هذه الممارسة التجميع في وقت التشغيل. تم دمج دعم "استوديو Android" لإنشاء برامج تظليل Vulkan.

يوفر الجزء المتبقي من هذه الصفحة مزيدًا من التفاصيل حول كل ممارسة، ثم يشرح كيفية دمج تجميع التظليل في تطبيق Vulkan الخاص بك.

فيديو مجمّع لمحتوى AOT

هناك طريقتان لتحقيق تجميع تظليل AOT، كما هو موضح في الأقسام التالية.

استخدام "استوديو Android"

من خلال وضع أدوات التظليل في app/src/main/shaders/، يتعرّف "استوديو Android" على أدوات التظليل من خلال امتدادات الملفات الخاصة بها، ويكمل الإجراءات التالية:

  • تجميع جميع ملفات أداة التظليل بشكل متكرر ضمن هذا الدليل.
  • إلحاق اللاحقة .spv بملفات أداة تظليل SPIR-V المجمّعة.
  • حزمة SPIRV-shaders في دليل assets/shaders/ لحزمة APK

سيحمِّل التطبيق أدوات التظليل المجمّعة من موقع assets/shaders/ المقابل في وقت التشغيل، وتكون بنية ملف تظليل spv المجمَّع هي نفسها بنية ملف تظليل GLSL للتطبيق ضمن app/src/main/shaders/:

AAsset* file = AAssetManager_open(assetManager,
                     "shaders/tri.vert.spv", AASSET_MODE_BUFFER);
size_t fileLength = AAsset_getLength(file);
char* fileContent = new char[fileLength];
AAsset_read(file, fileContent, fileLength);

يمكن ضبط علامات التجميع في Shaderc داخل مجموعة shaders لـ graderc، على النحو الموضّح في المثال التالي:

رائع

android {
  defaultConfig {
    shaders {
      glslcArgs.addAll(['-c', '-g'])
      scopedArgs.create('lights') {
        glslcArgs.addAll(['-DLIGHT1=1', '-DLIGHT2=0'])
      }
    }
  }
}

Kotlin

android {
  defaultConfig {
    shaders {
        glslcArgs += listOf("-c", "-g")
        glslcScopedArgs("lights", "-DLIGHT1=1", "-DLIGHT2=0")
    }
  }
}

تنطبق glslcArgs على جميع مجموعات أدوات التظليل، ولا تسري السمة scopedArgs إلا عند التجميع لهذا النطاق. ينشئ المثال أعلاه وسيطة نطاق lights، والتي سيتم تطبيقها فقط على أدوات تظليل GLSL ضمن الدليل app/src/main/shaders/lights/. يُرجى الرجوع إلى glslc للحصول على القائمة الكاملة لعلامات التجميع المتاحة. تجدُر الإشارة إلى أنّ Shaderc داخل NDK هو لقطة من مستودع github هذا في وقت إصدار NDK، ويمكنك الحصول على العلامات المتوافقة الدقيقة لهذا الإصدار باستخدام الأمر glslc --help، كما هو موضّح في القسم التالي.

تجميع سطر الأوامر بلا إنترنت

يمكن تجميع GLSL Shaders بتنسيق SPIR-V بشكل مستقل عن التطبيق الرئيسي باستخدام المحول البرمجي لسطر الأوامر glslc. ويتضمن الإصدار 12 من NDK والإصدارات الأحدث إصدارًا من glslc والأدوات ذات الصلة مسبقًا في دليل <android-ndk-dir>/shader-tools/ للتوافق مع نموذج الاستخدام هذا.

يتوفر برنامج التجميع أيضًا من مشروع Shaderc. اتّبِع التعليمات الواردة في تلك المقالة لإنشاء إصدار ثنائي.

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

وتجمع أداة glslc ملفًا أحادي المصدر في وحدة SPIR-V مع نقطة دخول واحدة لأداة التظليل. يحمل ملف الإخراج تلقائيًا الاسم نفسه المُستخدَم في الملف المصدر، ولكن مع إلحاق الامتداد .spv به.

يمكنك استخدام امتدادات أسماء الملفات لإعلام أداة glslc بمرحلة أداة تظليل الرسومات التي تريد تجميعها، أو ما إذا كان يتم تجميع برنامج تظليل الحوسبة. وللحصول على معلومات حول كيفية استخدام إضافات أسماء الملفات هذه والخيارات التي يمكنك استخدامها مع الأداة، راجع مواصفات مرحلة Shader في دليل glslc.

تجميع وقت التشغيل

بالنسبة إلى تجميع أدوات تظليل JIT أثناء وقت التشغيل، يوفر NDK مكتبة libshaderc، التي تحتوي على واجهات برمجة تطبيقات لـ C وC++.

يجب أن تستخدم تطبيقات C++ واجهة برمجة التطبيقات C++. ننصح بأن تستخدم التطبيقات المتوفّرة بلغات أخرى واجهة برمجة التطبيقات C API، لأنّ واجهة التطبيق الثنائية (ABI) ذات مستوى أدنى ومن المرجّح أن توفّر استقرارًا أفضل.

يوضح المثال التالي كيفية استخدام واجهة برمجة التطبيقات C++:

#include <iostream>
#include <string>
#include <vector>
#include <shaderc/shaderc.hpp>

std::vector<uint32_t> compile_file(const std::string& name,
                                   shaderc_shader_kind kind,
                                   const std::string& data) {
  shaderc::Compiler compiler;
  shaderc::CompileOptions options;

  // Like -DMY_DEFINE=1
  options.AddMacroDefinition("MY_DEFINE", "1");

  shaderc::SpvCompilationResult module = compiler.CompileGlslToSpv(
      data.c_str(), data.size(), kind, name.c_str(), options);

  if (module.GetCompilationStatus() !=
      shaderc_compilation_status_success) {
    std::cerr << module.GetErrorMessage();
  }

  std::vector<uint32_t> result(module.cbegin(), module.cend());
  return result;
}

الدمج في مشاريعك

يمكنك دمج المحول البرمجي لـ Vulkan Shadle في تطبيقك باستخدام ملف Android.mk للمشروع أو Gradle.

Android.mk

نفِّذ الخطوات التالية لاستخدام ملف Android.mk في مشروعك لدمج برنامج الترميز البرمجي لتظليل البيانات.

  1. أدرِج الأسطر التالية في ملف Android.mk:
    include $(CLEAR_VARS)
         ...
    LOCAL_STATIC_LIBRARIES := shaderc
         ...
    include $(BUILD_SHARED_LIBRARY)
    
    $(call import-module, third_party/shaderc)
    
  2. ضبط APP_STL على أي من c++_static أو c++_shared أو gnustl_static أو gnustl_shared في Application.mk

دمج أداة CMake المتعلقة بـ Gradle

  1. في نافذة المحطة الطرفية، انتقِل إلى ndk_root/sources/third_party/shaderc/.
  2. قم بتشغيل الأمر التالي لإنشاء Shaderc في NDK. عليك تشغيل هذا الأمر مرة واحدة فقط على كل إصدار NDK تستخدمه:
    $ ../../../ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
    APP_STL:=<stl_version> APP_ABI=all libshaderc_combined
    

    يضع هذا الأمر مجلدين في <ndk_root>/sources/rd_party/shaderc/. في ما يلي بنية الدليل:

    include/
      shaderc/
        shaderc.h
        shaderc.hpp
    libs/
      <stl_version>/
        {all of the abis}
           libshaderc.a
    
  3. أضِف قيم التضمين والمكتبات التي تم إنشاؤها باستخدام target_include_directories و target_link_libraries، كما تفعل عادةً مع المكتبات الخارجية المماثلة. يجب أن يتطابق نوع STL لتطبيقك مع أحد أنواع stl المحدّدة في stl_version. وينصح NDK باستخدام c++_shared أو c++_static، إلا أنّ gnustl_static وgnustl_shared متاحتان أيضًا.

الحصول على أحدث إصدار من Shaderc

إنّ Shaderc في NDK مصدره شجرة مصدر Android، وهي نبذة عن مستودع Shaderc repo الأساسي. إذا كنت بحاجة إلى أحدث إصدار من Shaderc، يُرجى الاطّلاع على تعليمات الإصدار للحصول على التفاصيل. وفي ما يلي الخطوات رفيعة المستوى:

  1. تنزيل أحدث إصدار من Shaderc:
    git clone https://github.com/google/shaderc.git
  2. تعديل التبعيات:
    ./utils/git-sync-deps
  3. إصدار Shaderc:
    <ndk_dir>/ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=Android.mk \
        APP_STL:=c++_static APP_ABI=all libshaderc_combined -j16
    
  4. اضبط مشروعك لاستخدام إصدار Shaderc الخاص بك في ملف النص البرمجي للإصدار.