ساختارهای داده کلیدی و نقش آنها در RenderingNG

کریس هارلسون
Chris Harrelson
دانیل چنگ
Daniel Cheng
فیلیپ راجرز
Philip Rogers
کوجی ایشی
Koji Ishi
ایان کیلپاتریک
Ian Kilpatrick
کایل شاربونو
Kyle Charbonneau

پست‌های قبلی در این مجموعه یک نمای کلی از اهداف، ویژگی‌های کلیدی و قطعات سطح بالای معماری RenderingNG ارائه می‌داد. اکنون بیایید ساختارهای داده کلیدی را که ورودی و خروجی خط لوله رندر هستند، بررسی کنیم.

این ساختارهای داده عبارتند از:

  • درختان فریم ، که از گره های محلی و راه دور تشکیل شده اند که نشان می دهد کدام اسناد وب در کدام فرآیند رندر قرار دارند و کدام رندر Blink.
  • درخت قطعه غیرقابل تغییر ، خروجی (و ورودی به) الگوریتم محدودیت طرح را نشان می دهد.
  • درختان ویژگی ، که نشان دهنده سلسله مراتب تبدیل، کلیپ، افکت و پیمایش یک سند وب هستند و در سراسر خط لوله استفاده می شوند.
  • لیست های نمایش و تکه های رنگ ورودی الگوریتم های شطرنجی و لایه بندی هستند.
  • فریم های کامپوزیتور سطوح، سطوح رندر و کاشی های بافت گرافیکی را که برای ترسیم با استفاده از GPU استفاده می شوند، محصور می کنند.

قبل از قدم زدن در میان این ساختارهای داده، می‌خواهم مثال ساده زیر را نشان دهم که بر روی یکی از پست قبلی ساخته شده است. من از این مثال چند بار در این پست استفاده می‌کنم و نشان می‌دهم که چگونه ساختارهای داده در آن اعمال می‌شوند.

<html>
  <div style="overflow: hidden; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
      id="one" src="foo.com/etc"></iframe>
  </div>
  <iframe style="top:200px;
    transform: scale(1.1) translateX(200px)"
    id="two" src="bar.com"></iframe>
</html>

درختان قاب

Chrome ممکن است گاهی اوقات انتخاب کند که یک فریم با منشاء متقاطع را در یک فرآیند رندر متفاوت از قاب اصلی خود ارائه دهد.

در مثال از مقدمه، سه فریم کلی وجود دارد:

یک قاب والد foo.com، حاوی دو iframe.

با جداسازی سایت، Chromium از دو فرآیند رندر برای ارائه این صفحه وب استفاده می‌کند. هر فرآیند رندر نمایش خاص خود را از درخت فریم برای آن صفحه وب دارد:

دو درخت فریم که نشان دهنده دو فرآیند رندر هستند.

یک فریم ارائه شده در یک فرآیند متفاوت به عنوان یک قاب از راه دور نشان داده می شود. یک قاب از راه دور حداقل اطلاعات مورد نیاز برای عمل به عنوان یک مکان نگهدار در رندر را در خود دارد، مثلاً ابعاد آن. در غیر این صورت، قاب از راه دور حاوی اطلاعات مورد نیاز برای ارائه محتوای واقعی آن نیست.

در مقابل، یک فریم محلی، فریمی را نشان می‌دهد که از خط لوله رندر استاندارد که در پست‌های قبلی توضیح داده شده است عبور می‌کند. فریم محلی شامل تمام اطلاعات مورد نیاز برای تبدیل داده های آن فریم (مانند درخت DOM و داده های سبک) به چیزی است که می تواند رندر و نمایش داده شود.

خط لوله رندر بر اساس دانه بندی قطعه درخت قاب محلی عمل می کند. مثال پیچیده تری را با foo.com به عنوان فریم اصلی در نظر بگیرید:

<iframe src="bar.com"></iframe>

و زیر فریم bar.com زیر:

<iframe src="foo.com/etc"></iframe>

اگرچه هنوز تنها دو رندر وجود دارد، اما اکنون سه قطعه درخت قاب محلی وجود دارد که دو قطعه در فرآیند رندر برای foo.com و یکی در فرآیند رندر برای bar.com هستند:

نمایشی از دو رندر و سه قطعه درخت فریم.

برای تولید یک فریم کامپوزیتور برای صفحه وب، Viz به طور همزمان از فریم ریشه هر یک از سه درخت فریم محلی یک فریم کامپوزیتور درخواست می کند و سپس آنها را جمع می کند . (در ادامه این پست به بخش فریم های کامپوزیتور نیز مراجعه کنید.)

فریم اصلی foo.com و زیرفریم foo.com/other-page بخشی از یک درخت فریم هستند و در یک فرآیند ارائه می شوند. با این حال، این دو فریم هنوز دارای چرخه عمر سند مستقل هستند زیرا بخشی از قطعات درخت قاب محلی مختلف هستند. به همین دلیل، امکان تولید یک فریم کامپوزیتور برای هر دو در یک به روز رسانی وجود ندارد. فرآیند رندر اطلاعات کافی برای ترکیب قاب کامپوزیتور ایجاد شده برای foo.com/other-page مستقیماً در قاب کامپوزیتور برای فریم اصلی foo.com ندارد. به عنوان مثال، فریم مادر خارج از فرآیند bar.com ممکن است با تبدیل iframe با CSS یا مسدود کردن بخش‌هایی از iframe با عناصر دیگر در DOM، بر نمایش iframe foo.com/other-url تأثیر بگذارد.

آبشار به روز رسانی اموال بصری

ویژگی‌های بصری مانند ضریب مقیاس دستگاه و اندازه دید در خروجی رندر شده تأثیر می‌گذارند و باید بین قطعات درخت قاب محلی همگام شوند. ریشه هر قطعه درخت فریم محلی یک شی ویجت مرتبط با آن دارد. به‌روزرسانی‌های ویژگی ویژوال قبل از ارسال به ویجت‌های باقی‌مانده از بالا به پایین، به ویجت فریم اصلی می‌روند. به عنوان مثال، هنگامی که اندازه Viewport تغییر می کند:

نمودار فرآیند توضیح داده شده در متن قبل.

این فرآیند آنی نیست، بنابراین ویژگی‌های بصری تکرار شده شامل یک نشانه همگام‌سازی نیز می‌شود. سازنده Viz از این نشانه همگام‌سازی استفاده می‌کند تا منتظر بماند تا تمام قطعات درخت قاب محلی یک فریم ترکیب‌کننده را با نشانه همگام‌سازی فعلی ارسال کنند. این فرآیند از اختلاط فریم های کامپوزیتور با ویژگی های بصری متفاوت جلوگیری می کند.

درخت قطعه غیرقابل تغییر

درخت قطعه غیرقابل تغییر خروجی مرحله طرح بندی خط لوله رندر است. این نشان دهنده موقعیت و اندازه همه عناصر در صفحه (بدون اعمال تبدیل) است.

نمایش قطعات در هر درخت، با علامت گذاری یک قطعه به عنوان نیاز به طرح.

هر قطعه نشان دهنده بخشی از یک عنصر DOM است. معمولاً فقط یک قطعه در هر عنصر وجود دارد، اما اگر هنگام چاپ در صفحات مختلف یا در یک زمینه چند ستونی در ستون‌ها تقسیم شود، ممکن است تعداد بیشتری نیز وجود داشته باشد.

پس از طرح، هر قطعه تغییر ناپذیر می شود و دیگر هرگز تغییر نمی کند. نکته مهم این است که ما چند محدودیت اضافی نیز قائل هستیم. ما این کار را نمی کنیم:

  • به هر ارجاع "بالا" در درخت اجازه دهید. (کودک نمی تواند یک اشاره گر به والدین خود داشته باشد.)
  • داده های "حباب" در درخت (کودک فقط اطلاعات را از فرزندان خود می خواند، نه از والدین خود).

این محدودیت‌ها به ما اجازه می‌دهد تا از یک قطعه برای طرح‌بندی بعدی استفاده مجدد کنیم. بدون این محدودیت‌ها، اغلب باید کل درخت را بازسازی کنیم، که گران است.

اکثر طرح‌بندی‌ها معمولاً به‌روزرسانی‌های افزایشی هستند، برای مثال، یک برنامه وب در پاسخ به کلیک کاربر روی یک عنصر، بخش کوچکی از رابط کاربری را به‌روزرسانی می‌کند. در حالت ایده‌آل، چیدمان باید فقط متناسب با آنچه روی صفحه تغییر کرده است انجام دهد. ما می‌توانیم با استفاده مجدد از هر چه بیشتر قسمت‌های درخت قبلی به این هدف برسیم. این بدان معنی است که (معمولا) ما فقط باید ستون فقرات درخت را بازسازی کنیم.

در آینده، این طراحی تغییرناپذیر به ما اجازه می‌دهد تا کارهای جالبی مانند عبور درخت قطعه تغییرناپذیر از مرزهای نخ در صورت نیاز (برای اجرای مراحل بعدی در یک رشته دیگر)، ایجاد چندین درخت برای یک انیمیشن چیدمان صاف، یا اجرای طرح‌بندی‌های فرضی موازی انجام دهیم. . همچنین به ما پتانسیل طرح‌بندی چند رشته‌ای را می‌دهد.

موارد قطعه درون خطی

محتوای درون خطی (متن سبک غالباً) از نمایش کمی متفاوت استفاده می کند. به جای یک ساختار درختی با جعبه ها و نشانگرها، محتوای درون خطی را در یک لیست مسطح نشان می دهیم که درخت را نشان می دهد. مزیت اصلی این است که نمایش لیست مسطح برای خطوط داخلی سریع است، برای بازرسی یا پرس و جوی ساختارهای داده درون خطی مفید است و حافظه کارآمد است. این برای عملکرد رندر وب بسیار مهم است، زیرا رندر متن بسیار پیچیده است و به راحتی می تواند به کندترین بخش خط لوله تبدیل شود مگر اینکه بهینه سازی شده باشد.

به عنوان یک یادداشت تاریخی جالب، این بسیار شبیه به نحوه ای است که اینترنت اکسپلورر قبلاً DOM خود را نشان می دهد زیرا در ابتدا به روشی مشابه به عنوان یک ویرایشگر متن ساخته شده بود.

فهرست مسطح برای هر زمینه قالب بندی درون خطی به ترتیب جستجوی عمقی در زیردرخت طرح بندی درون خطی آن ایجاد می شود. هر ورودی در لیست چند تا (شیء، تعداد فرزندان) است. به عنوان مثال، این DOM را در نظر بگیرید:

<div style="width: 0;">
  <span style="color: blue; position: relative;">Hi</span> <b>there</b>.
</div>

(توجه داشته باشید که ویژگی width روی 0 تنظیم شده است تا خط بین "سلام" و "آنجا" بپیچد.) هنگامی که زمینه قالب بندی درون خطی برای این وضعیت به صورت درختی نشان داده می شود، به شکل زیر است:

{
  "Line box": {
    "Box <span>": {
      "Text": "Hi"
    }
  },
  "Line box": {
    "Box <b>": {
      "Text": "There"
    }
  },
  {
    "Text": "."
  }
}

لیست تخت به این صورت است:

  • (جعبه خط، 2)
  • (جعبه <span>، 1)
  • (متن "سلام"، 0)
  • (جعبه خط، 3)
  • (جعبه <b>، 1)
  • (متن "آنجا"، 0)
  • (متن "."، 0)

مصرف کنندگان زیادی از این ساختار داده وجود دارد: APIهای دسترسی و APIهای هندسی مانند getClientRects و contenteditable . هر کدام نیازهای متفاوتی دارند. این اجزا از طریق یک مکان نما به ساختار داده مسطح دسترسی دارند.

مکان نما دارای APIهایی مانند MoveToNext ، MoveToNextLine ، CursorForChildren . این نمایش مکان نما به دلایل متعدد برای محتوای متنی بسیار قدرتمند است:

  • تکرار در ترتیب جستجوی عمقی بسیار سریع است. این بسیار اغلب استفاده می شود، زیرا شبیه به حرکات چرخشی است. از آنجایی که این یک لیست مسطح است، جستجوی اول عمق فقط افست آرایه را افزایش می دهد و تکرار سریع و محل حافظه را ارائه می دهد.
  • این جستجوی وسعت اول را ارائه می‌کند، که برای مثال، زمانی که پس‌زمینه جعبه‌های خطی و خطی را نقاشی می‌کنید، ضروری است.
  • دانستن تعداد فرزندان باعث می شود که سریع به سمت خواهر یا برادر بعدی حرکت کنید (فقط آرایه را با آن عدد افزایش دهید).

درختان ملکی

همانطور که می دانید، DOM درختی از عناصر (به اضافه گره های متنی) است و CSS می تواند سبک های مختلفی را برای عناصر اعمال کند.

اینها بیشتر در چهار طعم اثر می آیند:

  • Layout: ورودی های الگوریتم محدودیت طرح.
  • رنگ: نحوه رنگ آمیزی و شطرنجی عنصر (اما نه فرزندان آن).
  • بصری: جلوه‌های شطرنجی/طراحی که روی زیردرخت DOM اعمال می‌شود، مانند تبدیل‌ها، فیلترها و برش.
  • پیمایش: تراز محوری و برش گوشه گرد و پیمایش زیردرخت موجود.

درخت‌های ویژگی ساختارهای داده‌ای هستند که نحوه اعمال جلوه‌های بصری و پیمایشی را برای عناصر DOM توضیح می‌دهند. آنها ابزاری را برای پاسخ به سؤالاتی فراهم می کنند: با توجه به اندازه طرح و موقعیت آن، نسبت به صفحه، یک عنصر DOM داده شده کجاست؟ و: برای اعمال جلوه های بصری و اسکرول از چه ترتیبی از عملیات GPU باید استفاده شود؟

جلوه های بصری و اسکرول در وب در شکوه کامل خود بسیار پیچیده هستند. بنابراین مهم‌ترین کاری که درخت‌های ویژگی انجام می‌دهند این است که این پیچیدگی را به یک ساختار داده واحد ترجمه می‌کنند که دقیقاً ساختار و معنای آنها را نشان می‌دهد، در حالی که در عین حال بقیه پیچیدگی‌های DOM و CSS را حذف می‌کنند. این به ما امکان می دهد الگوریتم هایی را برای ترکیب و پیمایش با اطمینان بسیار بیشتری پیاده سازی کنیم. به خصوص:

  • هندسه مستعد خطا و سایر محاسبات را می توان در یک مکان متمرکز کرد.
  • پیچیدگی ساخت و به روز رسانی درختان دارایی در یک مرحله خط لوله رندر جدا شده است.
  • ارسال درخت‌های دارایی به رشته‌ها و فرآیندهای مختلف بسیار آسان‌تر و سریع‌تر از حالت DOM کامل است، در نتیجه استفاده از آنها برای بسیاری از موارد استفاده ممکن می‌شود.
  • هرچه موارد استفاده بیشتری وجود داشته باشد، بردهای بیشتری از کش هندسی ساخته شده در بالا بدست می آوریم، زیرا آنها می توانند از حافظه پنهان یکدیگر استفاده مجدد کنند.

RenderingNG از درخت های دارایی برای اهداف بسیاری استفاده می کند، از جمله:

  • جداسازی کامپوزیت از رنگ و کامپوزیت کردن از نخ اصلی.
  • تعیین استراتژی ترکیب / ترسیم بهینه
  • اندازه گیری هندسه IntersectionObserver .
  • اجتناب از کار برای عناصر خارج از صفحه و کاشی‌های بافت گرافیکی.
  • ابطال کارآمد و دقیق رنگ و شطرنجی.
  • اندازه گیری تغییر چیدمان و بزرگترین رنگ محتوایی در Core Web Vitals.

هر سند وب دارای چهار درخت ویژگی جداگانه است: transform، clip، effect و scroll. (یک تبدیل اسکرول به عنوان یک ماتریس تبدیل دوبعدی نشان داده می شود.) درخت کلیپ کلیپ های سرریز را نشان می دهد. درخت افکت همه جلوه‌های بصری دیگر را نشان می‌دهد: کدورت، فیلترها، ماسک‌ها، حالت‌های ترکیبی و انواع دیگر کلیپ‌ها مانند مسیر کلیپ. درخت اسکرول اطلاعاتی را در مورد پیمایش نشان می‌دهد، مانند اینکه چگونه اسکرول‌ها به یکدیگر متصل می‌شوند . برای انجام اسکرول روی رشته کامپوزیتور لازم است. هر گره در یک درخت ویژگی یک اسکرول یا جلوه بصری اعمال شده توسط یک عنصر DOM را نشان می دهد. اگر چندین اثر داشته باشد، ممکن است بیش از یک گره درخت ویژگی در هر درخت برای یک عنصر وجود داشته باشد.

توپولوژی هر درخت مانند یک نمایش پراکنده از DOM است. برای مثال، اگر سه عنصر DOM با کلیپ‌های سرریز وجود داشته باشد، سه گره درخت کلیپ وجود خواهد داشت و ساختار درخت کلیپ از رابطه بلوک حاوی بین کلیپ‌های سرریز پیروی می‌کند. همچنین پیوندهایی بین درختان وجود دارد. این پیوندها سلسله مراتب نسبی DOM و در نتیجه ترتیب کاربرد گره ها را نشان می دهد. به عنوان مثال، اگر یک تبدیل در یک عنصر DOM زیر یک عنصر DOM دیگر با یک فیلتر باشد، البته تبدیل قبل از فیلتر اعمال می شود.

هر عنصر DOM دارای یک حالت درخت ویژگی است که یک حالت 4 تایی (تبدیل، کلیپ، افکت، اسکرول) است که نزدیک‌ترین گره‌های درخت کلیپ، تبدیل و افکت را نشان می‌دهد که روی آن عنصر اثر می‌گذارند. این بسیار راحت است، زیرا با این اطلاعات ما دقیقاً لیست کلیپ ها، تبدیل ها و افکت هایی را می دانیم که برای آن عنصر اعمال می شود و به چه ترتیبی. این به ما می گوید که کجا روی صفحه است و چگونه آن را ترسیم کنیم.

مثال

( منبع )

<html>
  <div style="overflow: scroll; width: 100px; height: 100px;">
    <iframe style="filter: blur(3px);
      transform: rotateZ(1deg);
      width: 100px; height: 300px"
  id="one" srcdoc="iframe one"></iframe>
  </div>
  <iframe style="top:200px;
      transform: scale(1.1) translateX(200px)" id=two
      srcdoc="iframe two"></iframe>
</html>

برای مثال قبلی (که کمی متفاوت از مثال در مقدمه است)، در اینجا عناصر کلیدی درخت های ویژگی تولید شده آورده شده است:

نمونه ای از عناصر مختلف در درخت ویژگی.

نمایش لیست ها و تکه های رنگ

یک آیتم نمایشگر حاوی دستورات ترسیم سطح پایینی است ( اینجا را ببینید) که می توانند با Skia شطرنجی شوند. آیتم های نمایش معمولاً ساده هستند و فقط با چند دستور ترسیم مانند ترسیم یک حاشیه یا پس زمینه وجود دارد. پیاده‌روی درخت رنگ بر روی درخت طرح‌بندی و قطعات مرتبط به دنبال دستور نقاشی CSS تکرار می‌شود تا فهرست آیتم‌های نمایشی تولید شود.

مثلا:

یک جعبه آبی با عبارت "Hello world" در داخل یک مستطیل سبز.

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="blue" style="width:100px;
  height:100px; background:blue;
  position:absolute;
  top:0; left:0; z-index:-1;">
</div>

این HTML و CSS لیست نمایش زیر را تولید می کند که در آن هر سلول یک آیتم نمایش است:

پس زمینه را مشاهده کنید پس زمینه #blue #green پس زمینه سبز #متن درون خطی #green
drawRect با سایز 800x600 و رنگ سفید. drawRect با اندازه 100x100 در موقعیت 0.0 و رنگ آبی. drawRect با اندازه 80x18 در موقعیت 8،8 و رنگ سبز. drawTextBlob با موقعیت 8،8 و متن "Hello world".

لیست آیتم های نمایش داده شده پشت به جلو مرتب می شود. در مثال بالا، div سبز قبل از div آبی به ترتیب DOM است، اما ترتیب رنگ CSS مستلزم آن است که div آبی با شاخص z منفی قبل از ( مرحله 3 ) div سبز ( مرحله 4.1 ) رنگ آمیزی کند. موارد نمایش تقریباً با مراحل اتمی مشخصات سفارش رنگ CSS مطابقت دارند. یک عنصر DOM منفرد ممکن است منجر به چندین آیتم نمایشی شود، مانند اینکه #green یک آیتم نمایش برای پس‌زمینه و یک آیتم نمایش دیگر برای متن درون خطی دارد. این دانه بندی برای نشان دادن پیچیدگی کامل مشخصات سفارش رنگ CSS، مانند interleaving ایجاد شده توسط حاشیه منفی مهم است:

یک مستطیل سبز، با یک جعبه خاکستری تا حدی روی آن و عبارت "سلام دنیا".

<div id="green" style="background:green; width:80px;">
    Hello world
</div>
<div id="gray" style="width:35px; height:20px;
  background:gray;margin-top:-10px;"></div>

با این کار لیست نمایش زیر تولید می شود که در آن هر سلول یک آیتم نمایشگر است:

پس زمینه را مشاهده کنید #green پس زمینه سبز پس زمینه #gray #متن درون خطی #green
drawRect با سایز 800x600 و رنگ سفید. drawRect با اندازه 80x18 در موقعیت 8،8 و رنگ سبز. drawRect با اندازه 35x20 در موقعیت 8،16 و رنگ خاکستری. drawTextBlob با موقعیت 8،8 و متن "Hello world".

لیست آیتم های نمایشی ذخیره می شود و توسط به روز رسانی های بعدی مجددا استفاده می شود. اگر یک شی طرح بندی در طول پیاده روی درخت رنگ تغییر نکرده باشد، موارد نمایش آن از لیست قبلی کپی می شود. یک بهینه‌سازی اضافی متکی به ویژگی‌های سفارش رنگ CSS است: انباشتن زمینه‌ها به صورت اتمی رنگ می‌کنند. اگر هیچ شیء چیدمانی در یک زمینه انباشته شدن تغییر نکرده باشد، مسیر درخت رنگ از بافت انباشته می گذرد و کل دنباله آیتم های نمایشی را از لیست قبلی کپی می کند.

وضعیت درخت ویژگی فعلی در طول پیاده‌روی درخت رنگ حفظ می‌شود و فهرست آیتم‌های نمایشی به «تکه‌هایی» از آیتم‌های نمایشی گروه‌بندی می‌شود که حالت درخت ویژگی یکسانی دارند. این در مثال زیر نشان داده شده است:

جعبه صورتی با جعبه نارنجی کج.

<div id="scroll" style="background:pink; width:100px;
   height:100px; overflow:scroll;
   position:absolute; top:0; left:0;">
    Hello world
    <div id="orange" style="width:75px; height:200px;
      background:orange; transform:rotateZ(25deg);">
        I'm falling
    </div>
</div>

با این کار لیست نمایش زیر تولید می شود که در آن هر سلول یک آیتم نمایشگر است:

پس زمینه را مشاهده کنید #scroll پس زمینه #scroll متن درون خطی پس زمینه #orange متن درون خطی #orange
drawRect با سایز 800x600 و رنگ سفید. drawRect با اندازه 100x100 در موقعیت 0.0 و رنگ صورتی. drawTextBlob با موقعیت 0.0 و متن "Hello world". drawRect با اندازه 75x200 در موقعیت 0.0 و رنگ نارنجی. drawTextBlob با موقعیت 0,0 و متن "I'm falling".

درخت ویژگی تبدیل و تکه‌های رنگ پس از آن (برای اختصار ساده‌سازی می‌شود):

تصویری از جدول قبل، دو خانه اول در تکه 1، سومین خانه در تکه 2، دو خانه آخر در تکه 3.

فهرست مرتب شده از تکه‌های رنگ، که گروه‌هایی از آیتم‌های نمایشی و حالت درخت ویژگی هستند، ورودی‌های مرحله لایه‌بندی خط لوله رندر هستند. کل فهرست تکه‌های رنگ را می‌توان در یک لایه ترکیبی ادغام کرد و با هم شطرنجی کرد، اما هر بار که کاربر پیمایش می‌کرد این نیاز به شطرنجی‌سازی گران قیمت دارد. می‌توان یک لایه ترکیبی برای هر تکه رنگ ایجاد کرد و به‌صورت جداگانه شطرنجی کرد تا از همه‌ی تشریح‌سازی مجدد جلوگیری شود، اما به سرعت حافظه GPU را خسته می‌کند. مرحله لایه بندی باید بین حافظه GPU و کاهش هزینه ها در هنگام تغییر ایجاد کند. یک رویکرد کلی خوب این است که تکه‌ها را به‌طور پیش‌فرض ادغام کنیم، و تکه‌های رنگی را که حالت‌های درخت ویژگی‌هایی دارند که انتظار می‌رود در رشته ترکیب‌کننده تغییر کنند، مانند انیمیشن‌های تبدیل رشته ترکیب‌کننده یا تبدیل رشته‌های ترکیب‌کننده، ادغام نمی‌شوند.

مثال قبلی به طور ایده آل باید دو لایه ترکیبی تولید کند:

  • یک لایه ترکیبی 800x600 حاوی دستورات ترسیمی:
    1. drawRect با سایز 800x600 و رنگ سفید
    2. drawRect با اندازه 100x100 در موقعیت 0.0 و رنگ صورتی
  • یک لایه ترکیبی 144x224 حاوی دستورات ترسیمی:
    1. drawTextBlob با موقعیت 0.0 و متن "Hello world"
    2. ترجمه 0,18
    3. rotateZ(25deg)
    4. drawRect با اندازه 75x200 در موقعیت 0.0 و رنگ نارنجی
    5. drawTextBlob با موقعیت 0.0 و متن "I'm falling"

اگر کاربر #scroll را اسکرول کند، دومین لایه ترکیبی منتقل می‌شود، اما نیازی به شطرنجی نیست.

برای مثال در اینجا ، از بخش قبلی در مورد درختان دارایی، شش تکه رنگ وجود دارد. همراه با حالت های درخت ویژگی (تبدیل، کلیپ، افکت، اسکرول) آنها عبارتند از:

  • پس زمینه سند: اسکرول سند، کلیپ سند، ریشه، پیمایش سند.
  • گوشه افقی، عمودی و اسکرول برای div (سه تکه رنگ جداگانه): اسکرول سند، گیره سند، #one blur، پیمایش سند.
  • Ifframe #one : #one rotate، کلیپ اسکرول سرریز، #one blur، div scroll.
  • Iframe #two : #two مقیاس، کلیپ سند، ریشه، اسکرول سند.

فریم های کامپوزیتور: سطوح، سطوح رندر و کاشی های بافت گرافیکی

همانطور که در پست قبلی توضیح داده شد (نمونه کار شده در اینجا است)، فرآیندهای مرورگر و رندر، شطرنجی سازی محتوا را مدیریت می کنند و سپس فریم های کامپوزیتور را برای ارائه به صفحه به فرآیند Viz ارسال می کنند. فریم‌های Compositor چگونه RenderingNG را نشان می‌دهد که چگونه محتوای شطرنجی‌شده را به هم بچسبانید و آن را به طور کارآمد با استفاده از GPU ترسیم کنید.

کاشی

در تئوری، یک فرآیند رندر یا ترکیب‌کننده فرآیند مرورگر می‌تواند پیکسل‌ها را به یک بافت واحد به اندازه کامل نمای رندر تبدیل کند و آن بافت را به Viz ارسال کند. برای نمایش آن، سازنده نمایشگر فقط باید پیکسل ها را از آن بافت واحد در موقعیت مناسب در بافر فریم (مثلاً صفحه) کپی کند. با این حال، اگر آن کامپوزیتور بخواهد حتی یک پیکسل را به روز کند، باید نمای کامل را مجدداً شطرنجی کند و یک بافت جدید را به Viz ارسال کند.

در عوض، viewport به کاشی‌ها تقسیم می‌شود. یک کاشی بافت گرافیکی جداگانه هر کاشی را با پیکسل‌های شطرنجی بخشی از درگاه دید پشتیبان می‌دهد. سپس رندر می تواند کاشی های جداگانه را به روز کند یا حتی موقعیت کاشی های موجود را روی صفحه تغییر دهد. به عنوان مثال، هنگام پیمایش یک وب‌سایت، موقعیت کاشی‌های موجود به سمت بالا تغییر می‌کند و فقط گاهی اوقات یک کاشی جدید برای محتوای بیشتر در صفحه باید شطرنجی شود.

چهار کاشی.

تصویر بالا تصویری از یک روز آفتابی را با چهار کاشی نشان می دهد. هنگامی که یک اسکرول رخ می دهد، کاشی پنجم ظاهر می شود. یکی از کاشی ها اتفاقاً فقط یک رنگ (آبی آسمانی) دارد و یک ویدیو و یک آی فریم در بالا وجود دارد. که منجر به موضوع بعدی می شود.

چهارگوش و سطوح

کاشی‌های بافت گرافیکی نوع خاصی از چهارتایی هستند که فقط یک نام فانتزی برای یک دسته بافت یا دیگری است. چهارگانه بافت ورودی را مشخص می‌کند و نحوه تبدیل و اعمال جلوه‌های بصری روی آن را نشان می‌دهد. برای مثال، کاشی‌های محتوای معمولی دارای تبدیلی هستند که موقعیت x، y آنها را در شبکه کاشی نشان می‌دهد.

کاشی های بافت گرافیکی.

این کاشی‌های شطرنجی‌شده در یک پاس رندر پیچیده شده‌اند که فهرستی از چهارگوش است. پاس رندر حاوی هیچ اطلاعات پیکسلی نیست. در عوض، دستورالعمل‌هایی در مورد مکان و نحوه ترسیم هر کواد برای تولید خروجی پیکسل مورد نظر دارد. برای هر کاشی بافت گرافیکی یک چهارتایی ترسیمی وجود دارد. ترکیب‌کننده نمایشگر فقط باید فهرست چهارتایی‌ها را تکرار کند و هر کدام را با جلوه‌های بصری مشخص‌شده ترسیم کند تا خروجی پیکسل مورد نظر را برای پاس رندر تولید کند. ترکیب چهارتایی ترسیم برای پاس رندر را می توان به طور موثر بر روی GPU انجام داد، زیرا جلوه های بصری مجاز با دقت انتخاب می شوند تا به طور مستقیم به ویژگی های GPU نگاشت شوند.

فراتر از کاشی‌های شطرنجی، انواع دیگری از چهارتایی‌های ترسیمی وجود دارد. به عنوان مثال، چهارتایی ترسیم تک رنگ وجود دارد که به هیچ وجه با بافت پشتیبان نیستند، یا چهارتایی ترسیم بافت برای بافت های غیر کاشی مانند ویدیو یا بوم وجود دارد.

همچنین این امکان وجود دارد که یک فریم کامپوزیتور فریم دیگری را تعبیه کند. به عنوان مثال، کامپوزیتور مرورگر یک قاب ترکیب‌کننده با رابط کاربری مرورگر و یک مستطیل خالی که محتوای رندر کامپوزیتور در آن جاسازی می‌شود، تولید می‌کند. مثال دیگر iframe های ایزوله شده سایت است. این تعبیه از طریق سطوح انجام می شود.

هنگامی که یک کامپوزیتور یک فریم کامپوزیتور را ارسال می کند، با یک شناسه به نام شناسه سطحی همراه می شود که به سایر فریم های کامپوزیتور اجازه می دهد آن را با مرجع جاسازی کنند. جدیدترین فریم کامپوزیتور ارسال شده با شناسه سطحی خاص توسط Viz ذخیره می شود. یک فریم کامپوزیتور دیگر می‌تواند بعداً از طریق چهارتایی ترسیم سطحی به آن مراجعه کند، و بنابراین Viz می‌داند چه چیزی را بکشد. (توجه داشته باشید که کوادهای ترسیم سطحی فقط دارای شناسه سطح هستند و نه بافت.)

پاس های رندر متوسط

برخی از جلوه‌های بصری، مانند بسیاری از فیلترها یا حالت‌های ترکیبی پیشرفته، نیاز دارند که دو یا چند چهارتایی به یک بافت میانی کشیده شوند. سپس بافت میانی به یک بافر مقصد روی GPU (یا احتمالاً بافت میانی دیگری) کشیده می‌شود و همزمان جلوه بصری را اعمال می‌کند. برای اجازه دادن به این امر، یک فریم کامپوزیتور در واقع حاوی لیستی از پاس های رندر است. همیشه یک پاس رندر ریشه وجود دارد که آخرین آن ترسیم می شود و مقصد آن مربوط به بافر فریم است و ممکن است تعداد بیشتری نیز وجود داشته باشد.

امکان پاس های رندر متعدد، نام «رندر پاس» را توضیح می دهد. هر پاس باید به صورت متوالی بر روی GPU، در چندین "گذر" اجرا شود، در حالی که یک پاس واحد را می توان در یک محاسبات GPU موازی انبوه تکمیل کرد.

تجمع

چندین فریم ترکیب‌کننده به Viz ارسال می‌شوند و باید با هم به صفحه کشیده شوند. این کار توسط یک مرحله تجمع انجام می شود که آنها را به یک فریم ترکیبی واحد تبدیل می کند. Aggregation با فریم های کامپوزیتوری که آنها مشخص می کنند، چهارتایی رسم سطحی را جایگزین می کند. همچنین فرصتی برای بهینه‌سازی بافت‌های میانی غیرضروری یا محتوای خارج از صفحه است. به عنوان مثال، در بسیاری از موارد، فریم کامپوزیتور برای یک iframe ایزوله سایت نیازی به بافت میانی خود ندارد و می‌تواند مستقیماً از طریق quads ترسیم مناسب به درون بافر فریم کشیده شود. مرحله تجمیع چنین بهینه‌سازی‌هایی را مشخص می‌کند و آنها را بر اساس دانش جهانی که برای ترکیب‌کننده‌های رندر منفرد در دسترس نیست، اعمال می‌کند.

مثال

در اینجا فریم های کامپوزیتور واقعی هستند که نمونه ای از ابتدای این پست را نشان می دهند.

  • سطح foo.com/index.html : id=0
    • Render pass 0: draw to output.
      • Render pass draw quad: با تاری 3 پیکسل رسم کنید و در رندر پاس 0 کلیپ کنید.
        • رندر پاس 1:
          • برای محتویات کاشی #one iframe با موقعیت‌های x و y برای هر کدام، چهارتایی بکشید.
      • چهارتایی ترسیم سطحی: با شناسه 2، ترسیم شده با تبدیل مقیاس و ترجمه.
  • سطح رابط کاربری مرورگر: ID=1
    • Render pass 0: draw to output.
      • ترسیم quads برای رابط کاربری مرورگر (همچنین کاشی شده)
  • bar.com/index.html سطح: ID=2
    • Render pass 0: draw to output.
      • چهار عدد برای محتویات #two iframe با موقعیت های x و y برای هر کدام بکشید.

نتیجه

با تشکر برای خواندن! همراه با دو پست قبلی، این خلاصه مروری بر RenderingNG است. مرحله بعدی، بررسی عمیق چالش ها و فناوری در بسیاری از اجزای فرعی خط لوله رندر، از ابتدا تا انتها خواهد بود. آنها به زودی خواهند آمد!

تصاویر توسط Una Kravets.