RenderingNG의 주요 데이터 구조

Chris Harrelson
Chris Harrelson
Daniel Cheng
Daniel Cheng
Philip Rogers
Philip Rogers
Koji Ishi
Koji Ishi
Ian Kilpatrick
Ian Kilpatrick
Kyle Charbonneau
Kyle Charbonneau

렌더링 파이프라인의 입력과 출력인 주요 데이터 구조를 살펴보겠습니다.

이러한 데이터 구조는 다음과 같습니다.

  • 프레임 트리는 어떤 렌더링 프로세스와 어떤 Blink 렌더러에 있는 웹 문서를 나타내는 로컬 및 원격 노드로 구성됩니다.
  • 변경 불가능한 프래그먼트 트리는 레이아웃 제약 조건 알고리즘의 출력 및 입력을 나타냅니다.
  • 속성 트리는 웹 문서의 변환, 클립, 효과, 스크롤 계층 구조를 나타냅니다. 이는 파이프라인 전체에서 사용됩니다.
  • 디스플레이 목록 및 페인트 청크는 래스터 및 레이어링 알고리즘의 입력입니다.
  • 조합기 프레임은 GPU를 사용하여 그리기에 사용되는 노출 영역, 렌더링 노출 영역, GPU 텍스처 타일을 캡슐화합니다.

이러한 데이터 구조를 살펴보기 전에 다음 예에서는 아키텍처 검토의 예를 기반으로 합니다. 이 예시는 데이터 구조가 이 예에 적용되는 방식을 보여주는 데 사용되어 이 문서 전체에 걸쳐 사용됩니다.

<!-- Example code -->
<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은 상위 프레임과 다른 렌더링 프로세스에서 교차 출처 프레임을 렌더링하도록 선택할 수 있습니다.

예시 코드에는 총 3개의 프레임이 있습니다.

iframe 2개가 포함된 상위 프레임 foo.com

사이트 격리를 사용하면 Chromium은 두 개의 렌더링 프로세스를 사용하여 이 웹페이지를 렌더링합니다. 각 렌더링 프로세스에는 해당 웹페이지의 프레임 트리에 대한 자체 표현이 있습니다.

두 렌더링 프로세스를 나타내는 두 프레임 트리

다른 프로세스에서 렌더링된 프레임은 원격 프레임으로 표시됩니다. 원격 프레임은 렌더링에서 자리표시자로 작동하는 데 필요한 최소 정보(예: 크기)를 보유합니다. 그렇지 않으면 원격 프레임에는 실제 콘텐츠를 렌더링하는 데 필요한 정보가 포함되지 않습니다.

반면 로컬 프레임은 표준 렌더링 파이프라인을 통과하는 프레임을 나타냅니다. 로컬 프레임에는 해당 프레임의 데이터 (예: DOM 트리 및 스타일 데이터)를 렌더링하고 표시할 수 있는 것으로 변환하는 데 필요한 모든 정보가 포함됩니다.

렌더링 파이프라인은 로컬 프레임 트리 프래그먼트의 세분화 수준에서 작동합니다. foo.com를 기본 프레임으로 사용하는 더 복잡한 예를 생각해 보겠습니다.

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

다음 bar.com 하위 프레임도 있습니다.

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

렌더러는 여전히 2개이지만 이제 로컬 프레임 트리 프래그먼트가 3개 있습니다. foo.com의 렌더링 프로세스에 2개, bar.com의 렌더링 프로세스에 1개가 있습니다.

두 렌더링과 세 개의 프레임 트리 프래그먼트의 표현입니다.

웹페이지의 컴포저이터 프레임 하나를 생성하기 위해 Viz는 세 개의 로컬 프레임 트리의 각 루트 프레임에서 컴포저이터 프레임을 동시에 요청한 다음 이를 집계합니다. 합성기 프레임 섹션도 참고하세요.

foo.com 기본 프레임과 foo.com/other-page 하위 프레임은 동일한 프레임 트리의 일부이며 동일한 프로세스에서 렌더링됩니다. 그러나 두 프레임은 서로 다른 로컬 프레임 트리 프래그먼트의 일부이므로 여전히 독립적인 문서 수명 주기를 갖습니다. 따라서 한 번의 업데이트로 두 가지 모두에 대해 하나의 컴포저이터 프레임을 생성할 수 없습니다. 렌더링 프로세스에 foo.com/other-page용으로 생성된 컴포저 프레임을 foo.com 기본 프레임의 컴포저 프레임에 직접 합성할 만큼 충분한 정보가 없습니다. 예를 들어 프로세스 외부 bar.com 상위 프레임은 CSS로 iframe을 변환하거나 DOM의 다른 요소로 iframe의 일부를 가림으로써 foo.com/other-url iframe의 표시 상태에 영향을 줄 수 있습니다.

시각적 속성 업데이트 폭포식 차트

기기 배율과 표시 영역 크기와 같은 시각적 속성은 렌더링된 출력에 영향을 미치며 로컬 프레임 트리 프래그먼트 간에 동기화되어야 합니다. 각 로컬 프레임 트리 프래그먼트의 루트에는 위젯 객체가 연결되어 있습니다. 시각적 속성 업데이트는 기본 프레임의 위젯으로 이동한 후 위에서 아래로 나머지 위젯에 전파됩니다.

예를 들어 표시 영역 크기가 변경되면 다음과 같이 처리됩니다.

앞의 텍스트에 설명된 프로세스의 다이어그램

이 프로세스는 즉각적이지 않으므로 복제된 시각적 속성에는 동기화 토큰도 포함됩니다. Viz 컴포지터는 이 동기화 토큰을 사용하여 모든 로컬 프레임 트리 프래그먼트가 현재 동기화 토큰이 포함된 컴포지터 프레임을 제출할 때까지 기다립니다. 이 프로세스를 통해 컴포지터 프레임이 서로 다른 시각적 속성과 혼합되는 것을 방지할 수 있습니다.

변경 불가능한 프래그먼트 트리

변경 불가능한 프래그먼트 트리는 렌더링 파이프라인의 레이아웃 단계의 출력입니다. 변환이 적용되지 않은 페이지의 모든 요소의 위치와 크기를 나타냅니다.

각 트리의 프래그먼트 표현. 한 프래그먼트가 레이아웃이 필요하다고 표시되어 있습니다.

각 프래그먼트는 DOM 요소의 일부를 나타냅니다. 일반적으로 요소당 프래그먼트는 하나만 있지만, 인쇄 시 여러 페이지로 분할되거나 열이 여러 개인 컨텍스트에서는 열이 더 많을 수 있습니다.

레이아웃이 완료되면 각 프래그먼트는 변경 불가 상태가 되며 다시 변경되지 않습니다. 또한 몇 가지 추가 제한사항이 적용됩니다. Google에서 하지 않는 일:

  • 트리에서 'up' 참조를 허용합니다. 하위 요소는 상위 요소에 대한 포인터를 가질 수 없습니다.
  • 트리 아래로 데이터를 '부풀립니다'(하위 요소는 상위 요소가 아닌 하위 요소의 정보를 읽습니다).

이러한 제한사항을 통해 후속 레이아웃에 프래그먼트를 재사용할 수 있습니다. 이러한 제한이 없으면 전체 트리를 자주 다시 생성해야 하며 이는 비용이 많이 듭니다.

대부분의 레이아웃은 일반적으로 점진적인 업데이트입니다. 예를 들어 사용자가 요소를 클릭할 때 웹 앱이 UI의 일부를 업데이트하는 경우를 들 수 있습니다. 이상적으로는 레이아웃이 화면에서 실제로 변경된 것에 비례하여만 작업을 실행해야 합니다. 이전 트리의 많은 부분을 최대한 재사용하면 됩니다. 즉, 일반적으로 트리의 척추만 다시 빌드하면 됩니다.

향후 이 불변 설계를 통해 필요한 경우 스레드 경계를 넘어 불변 프래그먼트 트리를 전달하여(다른 스레드에서 후속 단계를 실행하기 위해), 원활한 레이아웃 애니메이션을 위해 여러 트리를 생성하거나, 병렬 추측 레이아웃을 실행하는 등의 흥미로운 작업을 할 수 있습니다. 또한 멀티스레딩 레이아웃 자체의 잠재력을 제공합니다.

인라인 프래그먼트 항목

인라인 콘텐츠 (주로 스타일이 지정된 텍스트)는 약간 다른 표현을 사용합니다. 상자와 포인터가 있는 트리 구조 대신 트리를 나타내는 평면 목록에 인라인 콘텐츠를 나타냅니다. 기본적인 이점은 인라인의 평면 목록 표현이 빠르고 인라인 데이터 구조 검사 또는 쿼리에 유용하며 메모리 효율적이라는 점입니다. 이는 웹 렌더링 성능에 매우 중요합니다. 텍스트 렌더링은 매우 복잡하며 고도로 최적화되지 않으면 파이프라인에서 가장 느린 부분이 될 수 있기 때문입니다.

평면 목록은 인라인 레이아웃 하위 트리의 깊이 우선 검색 순서대로 각 인라인 형식 지정 컨텍스트에 대해 생성됩니다. 목록의 각 항목은 (객체, 하위 요소 수)의 튜플입니다. 예를 들어 다음 DOM을 고려해 보세요.

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

width 속성이 0으로 설정되어 'Hi'와 'there' 사이에 줄이 래핑됩니다.

이 상황의 인라인 형식 지정 컨텍스트가 트리로 표시되면 다음과 같습니다.

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

평면 목록은 다음과 같습니다.

  • (선 상자, 2)
  • (상자 <span>, 1)
  • (텍스트 '안녕하세요', 0)
  • (선 상자, 3)
  • (상자 <b>, 1)
  • (텍스트 'there', 0)
  • (텍스트 '.', 0)

이 데이터 구조의 소비자는 접근성 API, getClientRectscontenteditable와 같은 도형 API 등 다양합니다. 각각 요구사항이 다릅니다. 이러한 구성요소는 편의 커서를 통해 플랫 데이터 구조에 액세스합니다.

커서에는 MoveToNext, MoveToNextLine, CursorForChildren와 같은 API가 있습니다. 이 커서 표현은 다음과 같은 여러 가지 이유로 텍스트 콘텐츠에 매우 강력합니다.

  • 깊이 우선 탐색 순서로 반복하면 매우 빠릅니다. 캐럿 이동과 유사하므로 매우 자주 사용됩니다. 평면 목록이므로 깊이 우선 탐색은 배열 오프셋을 증가시켜 빠른 반복과 메모리 지역성을 제공합니다.
  • 예를 들어 선 및 인라인 상자의 배경을 페인팅할 때 필요한 너비 우선 검색을 제공합니다.
  • 자손 수를 알면 다음 형제 요소로 빠르게 이동할 수 있습니다(배열 오프셋을 이 숫자로 증가시키기만 하면 됩니다).

속성 트리

DOM은 요소 트리 (텍스트 노드 포함)이며 CSS는 요소에 다양한 스타일을 적용할 수 있습니다.

다음 4가지 방법으로 표시됩니다.

  • 레이아웃: 레이아웃 제약 조건 알고리즘의 입력입니다.
  • Paint: 요소(자손 제외)를 페인트하고 래스터화하는 방법입니다.
  • 시각적: 변환, 필터, 클리핑과 같이 DOM 하위 트리에 적용된 래스터/드로잉 효과입니다.
  • 스크롤: 포함된 하위 트리의 축 정렬 및 둥근 모서리 클리핑 및 스크롤

속성 트리는 시각적 효과와 스크롤 효과가 DOM 요소에 적용되는 방식을 설명하는 데이터 구조입니다. 레이아웃 크기와 위치를 고려하여 지정된 DOM 요소가 화면에 대해 어디에 있는지와 같은 질문에 답변하는 수단을 제공합니다. 그리고 시각적 효과와 스크롤 효과를 적용하는 데 어떤 GPU 작업 시퀀스를 사용해야 하나요?

웹의 시각적 효과와 스크롤 효과는 그 자체로 매우 복잡합니다. 따라서 속성 트리가 하는 가장 중요한 일은 이러한 복잡성을 구조와 의미를 정확하게 나타내는 단일 데이터 구조로 변환하는 동시에 DOM 및 CSS의 나머지 복잡성을 제거하는 것입니다. 이를 통해 컴포지션 및 스크롤 알고리즘을 훨씬 더 확실하게 구현할 수 있습니다. 특히 다음 항목이 중요합니다.

  • 오류가 발생할 수 있는 도형 및 기타 계산을 한곳으로 중앙 집중화할 수 있습니다.
  • 속성 트리를 빌드하고 업데이트하는 복잡성은 하나의 렌더링 파이프라인 단계로 분리됩니다.
  • 속성 트리를 여러 스레드와 프로세스로 전송하는 것이 전체 DOM 상태보다 훨씬 쉽고 빠르므로 여러 사용 사례에 사용할 수 있습니다.
  • 사용 사례가 많을수록 서로의 캐시를 재사용할 수 있으므로 위에 빌드된 도형 캐시에서 더 많은 이점을 얻을 수 있습니다.

RenderingNG는 다음을 비롯한 다양한 목적으로 속성 트리를 사용합니다.

  • 페인트에서 합성, 기본 스레드에서 합성을 분리합니다.
  • 최적의 합성 / 그리기 전략 결정
  • IntersectionObserver 도형을 측정합니다.
  • 오프스크린 요소 및 GPU 텍스처 타일의 작업을 방지합니다.
  • 페인트와 래스터를 효율적이고 정확하게 무효화합니다.
  • Core Web Vitals에서 레이아웃 이동최대 콘텐츠 페인트를 측정합니다.

모든 웹 문서에는 변환, 클립, 효과, 스크롤이라는 4개의 별도 속성 트리가 있습니다.(*) 변환 트리는 CSS 변환 및 스크롤을 나타냅니다. 스크롤 변환은 2D 변환 행렬로 표시됩니다. 클립 트리는 오버플로 클립을 나타냅니다. 효과 트리는 불투명도, 필터, 마스크, 혼합 모드, clip-path와 같은 다른 종류의 클립 등 기타 모든 시각 효과를 나타냅니다. 스크롤 트리는 스크롤이 함께 연쇄되는 방식과 같은 스크롤에 관한 정보를 나타냅니다. 컴포저 스레드에서 스크롤을 실행하는 데 필요합니다. 속성 트리의 각 노드는 DOM 요소에 의해 적용된 스크롤 또는 시각적 효과를 나타냅니다. 여러 효과가 있는 경우 동일한 요소의 각 트리에 속성 트리 노드가 두 개 이상 있을 수 있습니다.

각 트리의 토폴로지는 DOM의 희소 표현과 같습니다. 예를 들어 오버플로 클립이 있는 DOM 요소가 3개 있는 경우 클립 트리 노드가 3개가 되고 클립 트리의 구조는 오버플로 클립 간의 포함 블록 관계를 따릅니다. 트리 간의 연결도 있습니다. 이러한 링크는 노드의 상대 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 페인팅 순서에 따라 레이아웃 트리와 연결된 프래그먼트를 반복하여 디스플레이 항목 목록을 생성합니다.

예를 들면 다음과 같습니다.

녹색 직사각형 안에 &#39;Hello world&#39; 문구가 있는 파란색 상자

<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 인라인 텍스트
크기가 800x600이고 색상이 흰색인 drawRect 크기가 100x100이고 위치가 0,0이며 색상이 파란색인 drawRect 8,8 위치에 크기가 80x18이고 색상이 녹색인 drawRect. 위치가 8,8이고 텍스트가 'Hello world'인 drawTextBlob

표시 항목 목록은 뒤에서 앞으로 정렬됩니다. 위 예에서 녹색 div는 DOM 순서에서 파란색 div 앞에 있지만 CSS 페인트 순서에서는 음수 z-index 파란색 div가 녹색 div (4.1단계)보다 먼저(3단계) 페인트되어야 합니다. 디스플레이 항목은 대략 CSS 페인트 순서 사양의 원자 단계에 해당합니다. 단일 DOM 요소가 여러 디스플레이 항목을 생성할 수 있습니다. 예를 들어 #green에는 배경용 디스플레이 항목과 인라인 텍스트용 디스플레이 항목이 있습니다. 이 세부사항은 음수 마진으로 생성된 인터리빙과 같은 CSS 페인트 순서 사양의 전체 복잡성을 나타내는 데 중요합니다.

회색 상자가 부분적으로 겹쳐져 있고 &#39;Hello world&#39;라는 문구가 있는 녹색 직사각형

<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 인라인 텍스트
크기가 800x600이고 색상이 흰색인 drawRect 8,8 위치에 크기가 80x18이고 색상이 녹색인 drawRect. 8,16 위치에 크기 35x20, 색상 회색인 drawRect 위치가 8,8이고 텍스트가 'Hello world'인 drawTextBlob

디스플레이 항목 목록은 나중에 업데이트될 때 저장되고 재사용됩니다. 페인트 트리 워크 중에 레이아웃 객체가 변경되지 않은 경우 표시 항목이 이전 목록에서 복사됩니다. 추가 최적화는 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 인라인 텍스트
크기가 800x600이고 색상이 흰색인 drawRect 크기가 100x100이고 위치가 0,0이며 색상이 분홍색인 drawRect 위치가 0,0이고 텍스트가 'Hello world'인 drawTextBlob drawRect: 크기 75x200, 위치 0,0, 색상 주황색 위치가 0,0이고 텍스트가 'I'm falling'인 drawTextBlob

그러면 변환 속성 트리와 페인트 청크는 다음과 같습니다 (간결성을 위해 단순화됨).

위의 표 이미지로, 청크 1의 처음 두 셀, 청크 2의 세 번째 셀, 청크 3의 마지막 두 셀이 표시되어 있습니다.

표시 항목 그룹과 속성 트리 상태인 페인트 청크의 순서가 지정된 목록은 렌더링 파이프라인의 레이어화 단계에 대한 입력입니다. 페인트 청크의 전체 목록을 단일 합성 레이어로 병합하고 함께 래스터화할 수 있지만, 이렇게 하면 사용자가 스크롤할 때마다 비용이 많이 드는 래스터화가 필요합니다. 모든 재래스터링을 방지하기 위해 페인트 청크별로 합성된 레이어를 만들고 개별적으로 래스터링할 수 있지만, 이렇게 하면 GPU 메모리가 빠르게 소모됩니다. 레이어화 단계에서는 GPU 메모리와 상황이 변경될 때의 비용 절감 간에 절충해야 합니다. 일반적으로 좋은 접근 방식은 기본적으로 청크를 병합하고 컴포지터 스레드에서 변경될 것으로 예상되는 속성 트리 상태가 있는 페인트 청크(예: 컴포지터 스레드 스크롤 또는 컴포지터 스레드 변환 애니메이션)는 병합하지 않는 것입니다.

앞의 예시에서는 이상적으로 두 개의 합성 레이어가 생성됩니다.

  • 그리기 명령어가 포함된 800x600 합성 레이어입니다.
    1. 크기가 800x600이고 색상이 흰색인 drawRect
    2. 크기가 100x100이고 위치가 0,0이며 색상이 분홍색인 drawRect
  • 그리기 명령어가 포함된 144x224 합성 레이어입니다.
    1. 위치가 0,0이고 텍스트가 'Hello world'인 drawTextBlob
    2. 0,18 번역
    3. rotateZ(25deg)
    4. drawRect: 크기 75x200, 위치 0,0, 색상 주황색
    5. 위치가 0,0이고 텍스트가 'I'm falling'인 drawTextBlob

사용자가 #scroll를 스크롤하면 두 번째 합성된 레이어가 이동하지만 래스터화는 필요하지 않습니다.

예를 들어 이전의 속성 트리 섹션에서 페인트 청크는 6개입니다. (변환, 클립, 효과, 스크롤) 속성 트리 상태와 함께 다음과 같습니다.

  • 문서 배경: 문서 스크롤, 문서 클립, 루트, 문서 스크롤
  • div의 가로, 세로, 스크롤 모서리 (세 개의 개별 페인트 청크): 문서 스크롤, 문서 클립, #one 흐리게 처리, 문서 스크롤
  • Iframe #one: #one 회전, 오버플로 스크롤 클립, #one 흐리게 처리, div 스크롤
  • Iframe #two: #two 크기 조정, 문서 클립, 루트, 문서 스크롤

컴포저 프레임: 노출 영역, 렌더링 노출 영역, GPU 텍스처 타일

브라우저 및 렌더링 프로세스는 콘텐츠의 래스터화를 관리한 후 화면에 표시하기 위해 컴포저 프레임을 Viz 프로세스에 제출합니다. 컴포저 프레임은 래스터화된 콘텐츠를 함께 스티치하고 GPU를 사용하여 효율적으로 그리는 방법을 나타냅니다.

카드

이론적으로 렌더링 프로세스 또는 브라우저 프로세스 컴포저는 픽셀을 렌더러 뷰포트의 전체 크기인 단일 텍스처로 래스터화하고 이 텍스처를 Viz에 제출할 수 있습니다. 이를 표시하려면 디스플레이 컴포저가 단일 텍스처의 픽셀을 프레임 버퍼의 적절한 위치(예: 화면)로 복사하기만 하면 됩니다. 그러나 해당 컴포저가 단일 픽셀을 업데이트하려면 전체 뷰포트를 다시 래스터화하고 Viz에 새 텍스처를 제출해야 합니다.

대신 뷰포인트가 타일로 나뉩니다. 별도의 GPU 텍스처 타일이 뷰포트의 일부에 대한 래스터화된 픽셀로 각 타일을 지원합니다. 그러면 렌더러가 개별 타일을 업데이트하거나 기존 타일의 화면 위치를 변경할 수 있습니다. 예를 들어 웹사이트를 스크롤할 때 기존 타일의 위치가 위로 이동하고 페이지 아래쪽에 있는 콘텐츠의 경우 가끔 새 타일을 래스터화해야 합니다.

타일 4개
이 이미지는 4개의 타일이 있는 화창한 날의 이미지를 묘사합니다. 스크롤이 발생하면 다섯 번째 카드가 표시되기 시작합니다. 카드 중 하나는 색상 (하늘색)이 하나만 있고 위에 동영상과 iframe이 있습니다.

쿼드 및 노출 영역

GPU 텍스처 타일은 특수한 종류의 사각형으로, 텍스처 카테고리의 한 가지에 대한 고급 이름일 뿐입니다. 쿼드는 입력 텍스처를 식별하고 시각 효과를 변환하고 적용하는 방법을 나타냅니다. 예를 들어 일반 콘텐츠 카드에는 카드 그리드의 x, y 위치를 나타내는 변환이 있습니다.

GPU 텍스처 타일

이러한 래스터화된 타일은 쿼드 목록인 렌더링 패스로 래핑됩니다. 렌더링 패스에는 픽셀 정보가 포함되지 않습니다. 대신 각 쿼드를 어디서 어떻게 그려 원하는 픽셀 출력을 생성할지에 관한 안내가 포함되어 있습니다. 각 GPU 텍스처 타일에 드로잉 쿼드가 있습니다. 디스플레이 컴포저는 렌더링 패스의 원하는 픽셀 출력을 생성하기 위해 쿼드 목록을 반복하여 각 쿼드를 지정된 시각적 효과로 그려 주기만 하면 됩니다. 허용되는 시각 효과는 GPU 기능에 직접 매핑되는 효과로 신중하게 선택되므로 렌더링 패스의 그리기 쿼드 컴포지션은 GPU에서 효율적으로 실행할 수 있습니다.

래스터라이즈된 타일 외에도 다른 유형의 그리기 쿼드가 있습니다. 예를 들어 텍스처로 전혀 지원되지 않는 단색 그리기 사각형이나 동영상이나 캔버스와 같은 카드가 아닌 텍스처의 텍스처 그리기 사각형이 있습니다.

컴포지터 프레임이 다른 컴포지터 프레임을 삽입할 수도 있습니다. 예를 들어 브라우저 컴포저는 브라우저 UI가 포함된 컴포저 프레임과 렌더링 컴포저 콘텐츠가 삽입될 빈 직사각형을 생성합니다. 사이트 격리된 iframe도 또 다른 예입니다. 이 삽입은 노출 영역을 통해 이루어집니다.

컴포저가 컴포저 프레임을 제출하면 노출 영역 ID라는 식별자가 함께 제공되므로 다른 컴포저 프레임이 참조를 통해 이를 삽입할 수 있습니다. 특정 노출 영역 ID로 제출된 최신 컴포저이터 프레임은 Viz에 저장됩니다. 그러면 나중에 다른 컴포저이터 프레임이 노출 영역 그리기 쿼드를 통해 이를 참조할 수 있으므로 Viz는 무엇을 그릴지 알 수 있습니다. 노출 영역 그리기 쿼드에는 텍스처가 아닌 노출 영역 ID만 포함됩니다.

중간 렌더링 패스

많은 필터나 고급 혼합 모드와 같은 일부 시각 효과는 두 개 이상의 쿼드를 중간 텍스처에 그려야 합니다. 그런 다음 중간 텍스처가 GPU의 대상 버퍼 (또는 다른 중간 텍스처)에 그려지면서 시각 효과가 동시에 적용됩니다. 이를 허용하기 위해 컴포저 프레임에는 실제로 렌더링 패스 목록이 포함되어 있습니다. 항상 루트 렌더링 패스가 있으며, 이 패스는 마지막으로 그리고 대상이 프레임 버퍼에 해당하며 더 있을 수 있습니다.

렌더 패스를 여러 번 실행할 수 있으므로 '렌더 패스'라는 이름이 붙었습니다. 각 패스는 여러 개의 '패스'로 GPU에서 순차적으로 실행되어야 하지만 단일 패스는 단일 대규모 병렬 GPU 계산으로 완료할 수 있습니다.

집계

여러 개의 컴포저이터 프레임이 Viz에 제출되며, 이러한 프레임은 함께 화면에 그려져야 합니다. 이는 단일 집계된 컴포저이터 프레임으로 변환하는 집계 단계를 통해 이루어집니다. 집계는 표시 영역 그리기 쿼드를 지정된 컴포지터 프레임으로 대체합니다. 또한 화면 밖에 있는 불필요한 중간 텍스처나 콘텐츠를 최적화할 수 있습니다. 예를 들어 사이트 격리 iframe의 컴포저 프레임은 대부분 자체 중간 텍스처가 필요하지 않으며 적절한 그리기 쿼드를 통해 프레임 버퍼에 직접 그릴 수 있습니다. 집계 단계에서는 이러한 최적화를 파악하고 개별 렌더링 컴포저가 액세스할 수 없는 전역 지식을 기반으로 이를 적용합니다.

다음은 이 게시물의 시작 부분에 나온 예를 나타내는 컴포저 프레임입니다.

  • foo.com/index.html 노출 영역: id=0
    • 렌더링 패스 0: 출력에 그립니다.
      • 렌더 패스 그리기 쿼드: 3픽셀 블러로 그리고 렌더 패스 0으로 클립합니다.
        • 렌더링 패스 1:
          • #one iframe의 타일 콘텐츠에 대한 사각형을 각각의 x 및 y 위치와 함께 그립니다.
      • 노출 영역 그리기 쿼드: ID 2이며 크기 조정 및 변환으로 그려집니다.
  • 브라우저 UI 노출 영역: ID=1
    • 렌더링 패스 0: 출력에 그립니다.
      • 브라우저 UI의 쿼드 그리기 (타일로도)
  • bar.com/index.html 표면: ID=2
    • 렌더링 패스 0: 출력에 그립니다.
      • #two iframe 콘텐츠의 사각형을 각각의 x 및 y 위치와 함께 그립니다.

삽화: 우나 크라베츠