تقديم التحسين للجوال ، الجزء 2. العائلات الرئيسية لوحدات معالجة الرسومات المحمولة الحديثة

تحية طيبة ، عشاق الأعزاء والمهنيين ، مبرمجين الرسومات! لنبدأ الجزء الثاني من سلسلة مقالاتنا حول تقديم التحسين للجوال. في هذا الجزء ، سننظر في العائلات الرئيسية لوحدات معالجة الرسومات التي يقدمها اللاعبون على الهاتف المحمول.


للبدء ، ضع في اعتبارك عددًا من المعايير التي يمكن من خلالها تصنيف وحدات معالجة الرسوميات المحمولة.

نواة تظليل موحدة أو متخصصة


في عصر بطاقات الفيديو المحمولة المبكرة ، قبل انتشار التأثيرات المعقدة ، كانت هناك وجهة نظر مفادها أنه بالنسبة لتظليل الأجزاء ، فإن الدعم للحسابات ذات الدقة المنخفضة يكفي. في الواقع ، في وضع العرض النموذجي ، يتم استخدام 8 بتات أو أقل لكل قناة ملونة. وقد أدى هذا الرأي إلى استخدام نوى تظليل متخصصة. بالنسبة للقمم ، استخدمنا نوى محسنة لتحويلات المصفوفة بدقة متزايدة FP24 / FP32 ( highp ). بالنسبة للبكسل ، النوى التي تعمل بشكل أكثر كفاءة مع دقة منخفضة FP16 ( متوسط ). مع هذا عاليةلم تكن مدعومة. للوهلة الأولى ، يتيح لنا هذا التخصص تحقيق توزيع أكثر عقلانية للترانزستورات على الشريحة. ومع ذلك ، من الناحية العملية ، يؤدي هذا إلى صعوبات في تطوير تأثيرات معقدة ، وكذلك عند استخدام مواد عالية الدقة. بالإضافة إلى ذلك ، يمكن أن يؤدي التخصص الأساسي إلى اختناق القمة / الشظية . يشير هذا المصطلح إلى الحالة عندما تكون بعض النوى "خاملة" ، بسبب الحمل غير المتماثل على نوى الرأس والبيكسل. 


لذلك ، تستخدم المعماريات الحديثة نوى موحدة. يمكن أن تتحمل هذه النواة مهام الرأس والبيكسل وغيرها من المهام الحسابية اعتمادًا على الحمل.


المتجه (SIMD) أو مجموعة التعليمات العددية


بروح الرغبة في توفير الترانزستورات الموصوفة أعلاه ، والمتخصصة في النوى ، تم تصميم مجموعة من تعليمات التظليل. تعمل معظم التحولات النموذجية للرسومات ثلاثية الأبعاد مع 4 متجهات مكونة. لذلك ، عملت GPUs المبكرة على وجه التحديد مع مثل هذه المعاملات. إذا احتوى كود التظليل على عمليات قياسية غير متجانسة لا يمكن للمحسن تعبئتها في عمليات المتجه بواسطة المحسن ، فلن يتم استخدام بعض قوة الحوسبة. يمكن توضيح هذه الظاهرة على النحو التالي:


هناك تظليل يقوم بتنفيذ عملية Multiply Add الشائعة: اضرب معاملين ، ثم قم بإضافة الثالث. عند الترجمة على بنية متجهية مشروطة (Vector ISA = هندسة مجموعة تعليمات المتجهات) نحصل على تعليمات متجه واحد vMADD ، والتي تعمل لمدة ساعة واحدة. في الهندسة العددية الشرطية ، نحصل على 4 تعليمات عددية ، والتي بفضل خط الأنابيب المحسن ، يتم تنفيذها أيضًا في دورة ساعة واحدة. ضع في اعتبارك الآن تظليلًا معقدًا ينفذ عمليتين ، ولكن على معاملين مكونين.


في حالة هندسة المتجهات ، نحصل بالفعل على تعليمات 2 تتطلب دورتين على مدار الساعة للتنفيذ. ومع ذلك ، لا يتم اتخاذ أي إجراء على مكونات .zw وقوة المعالجة خاملة. في حالة البنية العددية ، يمكن تعبئة هذه العمليات نفسها في 4 وحدات سمدية قياسية تعمل في نفس دورة الساعة. وبالتالي ، في العمارة العددية بسبب تحسين خط الأنابيب ، يتم تحقيق كثافة أعلى للحسابات. ومع ذلك ، كما هو موضح أدناه ، فإن ناقل ISA لا يزال ملائمًا. لذا ، من المنطقي تطبيق تقنيات المتجه لرمز التظليل. أنها تسمح لك بتحقيق أداء متزايد على بطاقات الفيديو مع ناقل ISA . في الوقت نفسه ، كقاعدة عامة ، هذا لا يضر بالأداء على عددي أكثر حداثةISA .

بناءً على الخصائص المذكورة أعلاه ، سنأخذ في الاعتبار عائلات وحدات معالجة الرسومات المحمولة الشائعة في عصرنا. لنبدأ بالعائلة الأكثر شيوعًا. يعرف الكثير من الناس أننا نتحدث عن بطاقات الرسومات مالي من شركة ARM البريطانية . لا تشارك ARM مباشرة في إنتاج الرقائق ، وتقدم الملكية الفكرية بدلاً من ذلك. مثل بطاقات الفيديو المحمولة الأخرى ، تعد مالي جزءًا من System on Chip (SoC) ، أي يعمل مع الذاكرة المشتركة لوحدة المعالجة المركزية ووحدة معالجة الرسومات والحافلة. 

مالي utgard


في عام 2008 ، ولد الممثلون الأوائل للهندسة المعمارية مالي أوتغارد ، حتى يومنا هذا. تتم تسمية بطاقات الفيديو هذه وفقًا لمخطط Mali-4 xx MP n ، حيث xx هو رقم الطراز و n هو عدد النوى الجزئية. في Mali Utgard Shader Core التخصص ، وجميع الموديلات تأتي بنواة واحدة فقط.

ميزات أخرى للهندسة المعمارية Mali Utgard:

  • برنامج OpenGL ES 2.0 
  • عدم وجود دعم عالي في حبات مجزأة
  • مجموعة تعليمات المتجه (من المنطقي تحويل الحسابات)

وعلى الرغم من برنامج OpenGL ES مواصفات ، مالي Utgard بطاقة الفيديو السائقين تجميع بنجاح تظليل جزء أن استخدام highp الدقة (على سبيل المثال، يتم تعيين دقة افتراضيا باستخدام الدقة highp تعويم ). ولكن يتم استخدام دقة متوسطة . لذلك ، من المستحسن أيضًا اختبار جميع أجهزة التظليل لألعاب الجوال على بطاقات الفيديو هذه. وفقًا للبيانات التي جمعتها Unity ، في نهاية عام 2019 ، عملت Mali Utgard على الأجهزة لحوالي 10 ٪ من اللاعبين. وإذا قمت بتعيين المرشحات المناسبة على market.yandex.ru ، يمكنك أن ترى أنه في عام 2019 تم الإعلان عن أكثر من 10 هواتف جديدة مع بطاقات فيديو من هذه البنية.


إذا كنت مستعدًا للتخلي عن هذا الجمهور ، يكفي أن تحدد متطلبات دعم OpenGL ES 3.0 في AndroidManifest.xml:

<uses-feature android:glEsVersion="0x00030000" android:required="true"⁄>

بالإضافة إلى Mali Utgard ، لا توجد حاليًا وحدات معالجة رسومات محمولة واسعة النطاق بدون دعم OpenGL ES 3.0.

وتجدر الإشارة بشكل خاص إلى استخدام مواد عالية الدقة في Mali Utgard . عشرة بتات من الجزء العشري بالدقة المتوسطة ليست كافية للنسج عالي الجودة مع دقة نسيج أكثر من 1024 على جانب واحد. ومع ذلك ، على الرغم من دعم الدقة المتوسطة فقط في نوى أجزاء Mali Utgard ، يمكنك الحصول على دقة تنسيق fp24 عند استخدام الاختلاف مباشرة.

// vertex shader
varying highp vec2 v_texc;
void main()
{
    v_texc = …;
}

//  fragment shader
...
varying highp vec2 v_texc;
void main()
{
    gl_FragColor = texture2D(u_sampler, v_texc); //  v_texc 
                                                 //  
}

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

بطاقة مالي متوسطة


و تم مالي Utgard الاستعاضة عن مالي مدكارد العمارة . هناك عدة أجيال من هذه العمارة مع أسماء الأنواع Mali-6xx و Mali-7xx و Mali-8xx . على الرغم من عمر 8 سنوات ، يمكن تسمية Mali Midgard بالهندسة المعمارية الحديثة التي توفر الدعم لمعظم الميزات الجديدة:

  • حبات شادر موحدة
  • برنامج OpenGL ES 3.2 (تظليل الحوسبة والهندسة ، التغطية بالفسيفساء ...)

ومع ذلك ، تحتفظ مالي Midgard ناقلات ISA . بالنظر إلى الاستخدام الواسع النطاق لـ Mali Midgard (حوالي 25 ٪ من جمهورنا) ، يصبح تحويل الحوسبة مناسبًا.

ميزة أخرى في Mali Midgard هي تقنية Forward Pixel Kill . يتم حساب كل بكسل في دفق منفصل من نواة الجزء. إذا أصبح من المعروف أثناء تنفيذ الدفق أن البكسل الناتج سيتم حظره بواسطة بكسل معتم من بدائي آخر ، ينتهي الدفق قبل الأوان ويتم استخدام الموارد المحررة لحسابات أخرى.

مالي bifrost


بجانب Midgard ، تبرز بنية Bifrost لانتقالها إلى ISA العددية . مقارنة بالهندسة السابقة ، تم زيادة الحد الأقصى لعدد النوى (من 16 إلى 32) ، ودعم واجهة محسنة مع وحدة المعالجة المركزية ، مما يسمح بوصول متماسك إلى الذاكرة المشتركة: تصبح التغييرات على محتويات ذاكرة CPU / GPU "مرئية" لبعضها البعض على الرغم من ذاكرة التخزين المؤقت ، يسمح لك بتبسيط التزامن.

من غير رسمي


تم إجراء العديد من المحاولات لعكس هندسة بطاقات الفيديو مالي لإنشاء برامج تشغيل مفتوحة المصدر لنظام Linux . تسمح لنا أعمال الأشخاص المتفانين الذين يحاولون القيام بذلك بإلقاء نظرة على الميزات غير الموثقة لبطاقات الفيديو في مالي . لذلك ، في مشروع PanFrost هناك أداة تفكيك لـ Mali Midgard / Bifrost ، والتي يمكنك من خلالها التعرف على مجموعة من تعليمات التظليل (لا توجد معلومات رسمية مفتوحة حول هذا الموضوع).


Adreno


الأسرة الثانية الأكثر شيوعًا لوحدات معالجة الرسومات المحمولة هي Adreno . بطاقة الفيديو هذه مثبتة على SoC ، المعروفة تحت العلامة التجارية Snapdragon ، من شركة Qualcomm الأمريكية . يتم تثبيت Snapdragon في الهواتف الذكية المتطورة في عصرنا من Samsung و Sony وغيرها.

بطاقات الفيديو الحالية من Adreno هي سلسلة العائلات 3xx - 6xx. تجمع كل هذه السلسلة بين الميزات التالية:

  • حبات شادر موحدة
  • Pseudo TBR (أحجام بلاط كبيرة تقع في ذاكرة GPU مخصصة تقليدية)
  • التحويل التلقائي في عرض الوضع الفوري اعتمادًا على طبيعة المشهد ( FlexRender )
  • مجموعة التعليمات العددية

بدءًا من Adreno 4xx ، تم تقديم دعم OpenGL ES 3.1 ، ومع Adreno 5xx - Vulkan و OpenGL ES 3.2 .

تقديم بلاط Adreno القائم


تحتوي بطاقات فيديو Adreno على وحدة معالجة رسومات "تقليدية" تسمى GMEM . تنطبق الأحجام من 128 كيلوبايت إلى 1536 كيلوبايت. هذا يسمح لك باستخدام حجم تجانب أكبر مقارنة ببنيات المطورين الآخرين لوحدات معالجة الرسومات المحمولة. في Adreno ، يكون حجم البلاط ديناميكيًا ويعتمد على تنسيق الألوان المستخدم ومخزن عمق الاستنسل. عند العمل في الوضع الفوري ، يحدث العرض في ذاكرة النظام. هناك امتداد GL ES يسمح لك بتحديد الوضع المفضل: QCOM_binning_control . ومع ذلك ، تشير أحدث التوصيات من Qualcomm إلى الاعتماد بالكامل على برامج تشغيل GPU ، والتي تحدد هي نفسها الوضع الأكثر تفضيلًا لمخزن الأوامر المؤقت الذي يتم إنشاؤه بواسطة التطبيق. 

عند العمل في وضع TBR يقوم Adreno بتمريرين قمة:

  1. تمرير Binning - توزيع المواد الأولية حسب الحاوية ( الصناديق ، مرادف للبلاط)
  2. تمرير قمة كاملة لتقديم فقط تلك البدائية التي تقع في الحاوية الحالية

أثناء مرور Binning ، يحسب Adreno مواقع قمة الرأس فقط. لا يتم حساب السمات الأخرى ، ويتم إزالة التعليمات البرمجية غير الضرورية من قبل المحسن. في الوثائق الرسمية (9.2 تحسين معالجة قمة الرأس) ، هناك توصية لتخزين معلومات قمة الرأس اللازمة لحساب المراكز بشكل منفصل عن بقية البيانات. هذا يجعل التخزين المؤقت لبيانات قمة الرأس أكثر كفاءة.

Freedreno


على عكس تقنيات ARM و Imagination ، تتردد شركة Qualcomm في مشاركة تفاصيل الهيكل الداخلي لوحدات معالجة الرسومات الخاصة بها. ومع ذلك ، وبفضل جهود المهندس العكسي Rob Clark ، يمكن تعلم الكثير من مشروع Freedreno ، برنامج تشغيل Adreno مفتوح المصدر لبرنامج Linux.

روب كلارك من Freedreno

PowerVR بواسطة تقنيات الخيال


Imagination Technologies هي شركة بريطانية مشهورة تشتهر بتطوير GPUs لمنتجات Apple. قامت الشركة بهذا الدور حتى ظهور iPhone 8 / X ، الذي يستخدم التطوير الداخلي لشركة Apple. على الرغم من أن التوصيات بشأن التحسينات لهذه الرقائق التي لم تتغير ، وكذلك مطالبات براءات الاختراع ضد Apple من Imagination تشير إلى أن Apple واصلت تطوير بنية PowerVR ، وهو تطور أصلي من Imagination. في أوائل عام 2020 ، عادت Apple إلى ممارسات الترخيص مع Imagination Technologies. بالإضافة إلى الأجهزة التي تعمل بنظام iOS / iPadOS ، يتم تثبيت بطاقات فيديو PowerVR في عدد كبير من الهواتف الذكية والأجهزة اللوحية التي تعمل بنظام Android.


ضع في اعتبارك عائلة بطاقات رسومات PowerVR التي لا تزال موجودة بين المستخدمين.

PowerVR SGX


ظهرت أولى بطاقات الرسوميات PowerVR SGX في عام 2009. هناك عدة أجيال من هذه الهندسة المعمارية: Series5 و Series5XT و Series5XE. استخدمت Apple وحدات معالجة الرسومات هذه حتى iPAD 4 / iPhone 5 / iPOD Touch 5. ويمكن الاستشهاد بميزات SGX التالية:

  • حبات شادر موحدة
  • برنامج OpenGL ES 2.0
  • مجموعة تعليمات المتجه
  • دعم الدقة المنخفضة 10 بت في التظليل
  • يقرأ أداء منخفض من نسيج تابع

دعونا نتناول بعض منها بمزيد من التفصيل. 

دقة منخفضة


إن PowerVR SGX هي وحدات معالجة الرسوميات المحمولة
الوحيدة التي تدعم الأجهزة المنخفضة . تستخدم موديلات PowerVR الأحدث ، بالإضافة إلى جميع وحدات معالجة الرسومات الحديثة من البائعين الآخرين ، دقة متوسطة . يتيح لك استخدام
lowp على PowerVR SXG تحقيق كثافة حسابية أعلى (المزيد من العمليات لكل دورة). في الوقت نفسه ، فإن عملية التمشيط (تبديل مكونات المتجه) للورق ، على عكس الدقة الأخرى ، ليست مجانية. هذه الميزة ، بالإضافة إلى النطاق الضيق من القيم التي توفرها lowp ([-2،2]) ، يحد من نطاقها. في نفس الوقت ، ضعاف مجموعة الإعدادمما ينتج عنه قطع أثرية على عائلة SGX لن يتم رؤيتها على جميع بطاقات الرسومات الأخرى حيث سيتم استخدام دقة متوسطة . لهذا السبب ، يجب أن تفكر في رفض استخدام برنامج lowp في التظليل.

يقرأ نسيج تابع


كما تعلمون ، فإن عمليات أخذ عينات النسيج هي الأبطأ بسبب الحاجة إلى انتظار نتائج قراءة الذاكرة. في حالة SoC المحمول ، نتحدث عن ذاكرة النظام المشتركة مع وحدة المعالجة المركزية. لتقليل عدد عمليات الوصول إلى الذاكرة البطيئة ، يتم استخدام ذاكرة التخزين المؤقت للنسيج. لتجنب وقت التوقف في بداية التنقيط باستخدام مادة ، فمن المنطقي تخزين المناطق المستخدمة مسبقًا. إذا كان جهاز تظليل الجزء يستخدم إحداثيات النسيج التي تم تمريرها من جهاز تظليل الرأس بدون تغييرات ، فيمكن تحديد قسم النسيج اللازم للتخزين المؤقت قبل تنفيذ جهاز تظليل الجزء. إذا قام تظليل الجزء بتغيير تنسيق النسيج أو حسابه باستخدام بيانات من نسيج آخر ، فهذا ليس ممكنًا دائمًا. نتيجة لذلك ، قد يتباطأ تنفيذ جهاز تظليل الشظايا.تعتبر بطاقات الرسومات PowerVR SGX مؤلمة بشكل خاص في هذا السيناريو. علاوة على ذلك ، حتى استخدام التقليب لمكونات إحداثيات النسيج (الضرب) يؤدي إلىقراءة الملمس التابعة . هنا مثال لبرنامج تظليل بدون قراءة نسيج تابع .

برنامج القمة

attribute highp vec2 a_texc;
varying highp vec2 v_texc;

void main()
{
	gl_Position = …
	v_texc = a_texc;
}


برنامج تجزئة

precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;

void main()
{
	gl_FragColor = texture2D( u_sampler, v_texc ); //  dependent texture read
}

في هذه الحالة:

برنامج التجزئة

precision mediump float;
uniform sampler u_sampler;
varying highp vec2 v_texc;

void main()
{
	gl_FragColor = texture2D( u_sampler, v_texc.yx ); // dependent texture read!
}

باور في روغ


تم تطوير بطاقات فيديو PowerVR بشكل أكبر في بنية Rogue . هناك عدة أجيال من هذه البنية: من Series6 إلى Series9. تحتوي جميع PowerVR Rogue على الميزات التالية:

  • حبات شادر موحدة
  • هندسة التدريس العددية
  • دعم OpenGL ES 3.0+ (حتى 3.2 ، بالإضافة إلى Vulkan API للحكام الجدد) 

PowerVR TBDR


مثل جميع وحدات معالجة الرسومات المحمولة الشائعة ، يستخدم PowerVR خط أنابيب البلاط. ولكن على عكس منافسيها ، ذهب Imagination إلى أبعد من ذلك ونفذ تنقيطًا مؤجلًا للبدائيات ، مما يسمح بتخطي تظليل وحدات البكسل غير المرئية بغض النظر عن ترتيب العرض. يُطلق على هذا الأسلوب اسم التقديم المؤجل القائم على البلاط ، وتسمى عملية إزالة وحدات البكسل غير المرئية إزالة السطح المخفي (HSR).


إزالة السطح المخفي من

المستحسن رسم هندسة غير شفافة إلى شفافة وعدم استخدام Z Prepass ، والتي في حالة بطاقات الفيديو PowerVR في معظم السيناريوهات ستؤدي إلى عمل غير ضروري. ومع ذلك ، يتم تظليل العديد من وحدات البكسل الشفافة المتتابعة المتداخلة تمامًا للحصول على اللون الصحيح ، مع مراعاة الخلط. يمكن تجاهل آخر بكسل شفاف إذا تبعه بكسل غير شفاف. 

تقنيات الخيال الانفتاح


قدم مبدعو PowerVR وثائق مفتوحة للوصول إلى وثائق أكثر من مطوري GPU الآخرين. يتم وصف هندسة خط الأنابيب بالتفصيل ، بالإضافة إلى مجموعة من التعليمات الخاصة بهندسة Rogue . هناك أداة ملائمة PVRShaderEditor ، والتي تسمح لك بتلقي معلومات التنميط على الفور على التظليل ، بالإضافة إلى القائمة المفككة لـ Rogue.


على الرغم من التواجد المحدود لبطاقات فيديو PowerVR في بيئة الأجهزة القائمة على Android ، فمن المنطقي دراسة هندستها من أجل البرمجة المختصة للرسومات لنظام iOS.

وحدات معالجة الرسومات المحمولة في الوضع الفوري


قمنا بفحص العائلات الأكثر شيوعًا لبطاقات الفيديو المحمولة. استخدمت جميع هذه العائلات هندسة تجانب البلاط. ومع ذلك ، هناك بطاقات فيديو محمولة تستخدم نهج الوضع الفوري التقليدي . هنا بعض منهم:

  • nVIdia (Tegra SoC)
  • جميع عائلة إنتل باستثناء الجيل 11 الأخير
  • Vivante GCxxxx (+ Arcturus GC8000)

إحدى ميزات بطاقات الفيديو المحمولة التي تعمل في الوضع الفوري هي عملية تنظيف FBO باهظة الثمن. تذكر أنه في هندسة البلاط ، يعمل التنظيف بملء الشاشة على زيادة سرعة العرض ، مما يسمح للسائق بعدم إضافة عملية تحميل المحتويات القديمة إلى ذاكرة البلاط. في وحدات معالجة الرسومات في الوضع الفوري للجوّال ، يُعد التنظيف في وضع ملء الشاشة عملية تستغرق وقتًا طويلاً وتتيح ، من بين أشياء أخرى ، وحدات معالجة الرسومات هذه "الحساب". إذا كانت إضافة التنظيف لا تسرع ، ولكنها تبطئ العرض ، فمن المرجح أننا نعمل مع GPU في الوضع الفوري . حسنًا ، بالطبع ، لا ننسى أن نذكر أنه في وحدات معالجة الرسومات في الوضع الفوري ، فإن تغيير الهدف هو إجراء "مجاني مشروط".

توزيع العائلات المختلفة لوحدات معالجة الرسومات المحمولة بين اللاعبين


فيما يلي الإحصائيات الخاصة بوحدات معالجة الرسومات المحمولة التي تم جمعها من لاعبينا في نهاية عام 2019:


أدناه نفتح شريحة "الآخرين"


استنادًا إلى هذه البيانات ، ننظر إلى توزيع GPU من حيث ميزاتها الرئيسية.


تصبح وحدات ALU المتجهية (وحدة المنطق الحسابي) قديمة واستبدالها بمقياس عددي. اليوم ، الجزء الأكبر من GPUs المحمولة مع مجموعة تعليمات ناقلات هو Mali Midgard ، والتي يمكن اعتبارها متوسطة في الأداء. لان كقاعدة ، لا تبطئ عملية التنفيذ على وحدات ALU العددية ؛ يجدر النظر في التحويل كطريقة فعلية لتحسين أجهزة التظليل للجوال. 

يتم إهمال حبات التظليل المتخصصة واستبدالها بأخرى موحدة. اختناق Vertex على شبكة الهيكل العظمي لم يعد مخيفا. يتم استخدام النوى المتخصصة فقط في عائلة Mali-4xx (Utgard) . تذكر أن وحدات معالجة الرسومات هذه تدعم OpenGL ES 2.0 فقط . جمهورنا لديه حوالي 3.5٪ منهم.

أخيرًا ، تستخدم الغالبية العظمى من وحدات معالجة الرسوميات المحمولة طريقة التجانب. أصبح الوضع الفوري مهمشًا ويتم ضغطه بسرعة إلى جانب بطاقات الفيديو التي تستخدمه. تبلغ حصة GPUs في الوضع الفوري في لاعبينا حوالي 0.7 ٪.

روابط مفيدة:


شكرا للانتباه! في المقالة التالية من السلسلة ، سننظر في تقنيات تحسين تظليل للجوال.

All Articles