ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [16] - Swap Chain
    Graphics 2021. 7. 19. 22:00

     

    D3D는 일반적으로 COM 바탕으로 Object Oriented Architecture의 형태를 갖추고 있습니다. 이제 Device라는 개념이 등장합니다. 조금 복잡한 개념이지만 당장은 Rendering을 하기 위해 필요한 자원들을 배분해주는 역할을 수행한다고 알면 될 것 같습니다. 이 Device는 '논리적 그래픽 카드'이며 물리적 그래픽 카드나 Software Emulation Layer의 도움을 받기도 합니다. 앞으로 D3D에서 graphics Pipeline을 구축할 때, 이 Device의 Object를 통해 필요한 자원들을 할당할 것입니다.

    거의 모든 자원들이 device object를 통해 배분됩니다

    그 중에서도 Swap Chain은 다중 프레임 버퍼[Multiple frame buffer]를 갖고 있는데 이 각각의 프레임 버퍼에 접근하기 위해 오브젝트들을 만들 수도 있습니다. 그리고 그림에 보면 View라는 것들이 달려있는데 이 view들이 각 자원[Resource]들(예를 들면, vertex라든가 texture)을 Shader Pipeline과 묶어주는 역할을 합니다.

    device 자체는 D3D가 제공하는 Factory function에 의해 생성이 되고 이 Device object로 Swap chain을 얻기 위해서 DXGIAdapter와 같은 자잘한 일들을 진행하게 됩니다. 그나저나 Swap Chain이란 것이 대체 무엇일까요?

    Swap Chain

    Swap chain은 실질적으로 모니터에 픽셀 데이터[Pixel Data]가 나타날 수 있도록 해줍니다. 좌측처럼 비디오 메모리[Video Memory]에 적당한 블록을 프레임 버퍼[Frame Buffer]라고 하는데 여기엔 모니터에 나타날 각종 픽셀 정보들이 존재합니다. 여기서 그래픽 어댑터Graphics Adapter]가 하는 일은 프레임 버퍼를 쭉 Scan하여 읽고 HDMI든 DP든 적합한 포맷[Format]으로 모니터에 전송합니다.

    그러면 모니터에서도 똑같이 Row by Row로 좌측 상단부터 우측하단까지 표시가 될 것입니다. 우측 하단에 도달하면 다시 좌측 상단으로 돌아가서 같은 과정을 반복합니다.여기서 잠깐 이렇게 하나의 Frame buffer와 모니터 사이에서만 작업이 일어날 경우에 발생하는 일이 있습니다.

    만일, 프레임 버퍼 상의 중간 정도를 스캔하고 있는데 이미 지나온 지점에 새로운 픽셀 정보가 들어온다면 모니터에는 그것이 표시되지 않는 경우가 발생할 수 있습니다. 사실 어떤 오브젝트를 얼마나 빠르게 그릴 수 있느냐가 관건이긴 합니다. 또 같은 이유에서 아까는 없었던 물체가 모니터 상에 나타났다가 사라졌다가 어떤 때는 반만 나타날 수가 있습니다. 이런 형태의 그래픽 처리 방식을 Single Buffering이라고 합니다. 오류를 지칭하는 말이 아니고 그냥 이렇게 모니터에 표시하는 스키마를 Single buffering이라고 합니다. 그리고 당연히 안 쓰는 기법이 되어 버렸습니다.

    대신 좌측 그림과 같이 두 개의 프레임 버퍼를 사용해서 렌더링을 하기로 했습니다. Front/Back Buffer는 각각 모니터에 출력할 것과 실질적으로 작업 중인 화면을 가리킵니다.그렇기 때문에 Front는 거의 바뀌는 것이 없어 정적이고 Back은 계속 작업을 거치기 때문에 상당히 동적입니다.

    좌측 그림의 스캔하는 부분 이전의 위치에 아직 다 못그린 파란색 원이 생겨버리면 모니터에는 표시가 되지 않았을 겁니다. 그러나 Back buffer를 導入한다면 한 화면이 온전히 완료되고 나서야 화면에 출력되기 때문에 깜빡거림이나 잘려나오는 현상을 보기 힘들 것입니다.

    두 버퍼 Back/Front를 교환하는 방법에는 보통 Flip을 하거나 이름만 바꿔서 포인터를 쥐어주는 방법이 있습니다. 무슨 말인가? Front를 모니터로 열심히 보내주다가 Back이 완료가 되면 Back의 이름을 Front로 바꾸어서 Front로 쓰고 기존 Front를 Back으로 바꾸어 여기서 작업을 시작하는 겁니다.

    그럼에도 불구하고 모든 오류를 제거한 건 아닌데, 대표적으로 Tearing현상이 있습니다. front와 back을 사용한 Swap chain에서 아직 다 그리지를 못했는데 Flip해버리면 그리다가 만 영상이 모니터로 출력되게 됩니다. https://forum.enlisted.net/t/xbox-series-x-screen-tearing/12054

     

    XBOX SERIES X Screen tearing

    I currently have thirty games installed on my xbox x series and have no SCREEN TEARING issues (Panasonic TX-40AX630E 4K TV) I have SCREEN TEARING problems only with ENILSTED, nobody can answer me why? I add photos for demonstration.

    forum.enlisted.net

    해결책은 너무나 당연하게도 완전히 모니터 상에서 출력을 마치고 다시 최상단에서 출력준비를 끝마치러 가는 찰나의 순간에 Flip을 수행하는 것입니다. 그리고 이게 우리가 할 일입니다. 놀랍게도 D3D가 이 기능을 제공하기도 하며 '찰나'라는 순간을 지정해 줄수도 있습니다. 물론 약간의 딜레이가 생길 가능성이 생기긴 합니다. 몇몇 프레임에 지연이 생기거나 스킵을 해야하는 순간이 생기기 때문입니다. 그래서 세 개의 버퍼를 쓰기도 합니다. 어찌됐든 중요한 건, Swap Chain은 Frame Buffer의 집합체라는 사실입니다.

    이제 우리가 해야할 건 V-Sync라고 해서 한 번의 스캔이 끝날 때까지 모니터로 Front buffer의 픽셀 정보를 보내지 않게 하여 Tearing현상을 제거하는 겁니다. 이건 앞으로 진행할 내용의 요약입니다. : DXGI가 Swap Chain을 만드는데 사용되고 Swap Chain이 Frame Buffer의 집합체라고 했으니 Swap chain으로부터 Back buffer를 얻고 이로부터 다시 RenderTarget을 만듭니다. 그리고 이 Render Target를 Graphics Pipeline에 Bind할 것입니다.

    DXGI

    이건 뭘까요? D3D와 다른 요소일까요? 다른 요소이긴 합니다. DXIG는 DirectX 9, 11, 12 등등에서 다른 함수들에 비해 잘 변하지 않는 기능들이나 비교적 Low level-behaviour들을 모아 놓은 것이라고 보면 편합니다. 그래서 Swap chain을 만드는 기능이 바로 이 DXGI가 담당하는 것입니다.

    Device는 추가적으로 Context라는 것을 만듭니다. 이 Object는 굉장히 중요하게 다루어질 예정인데, 왜냐하면 이 오브젝트가 Graphics Adapter를 대표하기[Represent]때문입니다. 그런데 차차 알아가겠지만 기능이 Device와 상당히 유사한데 결정적인 차이점은 Device는 주로 Resource의 분배를 담당하고 다른 Objects의 생성에 집중하지만 Context는 Rendering Commands를 제공하고 Rendering Pipeline을 구성합니다. 간단하게 생각하면 Device는 Setup이고 Context는 Execution입니다.

    그러면, 이 Context는 D3D11CreateDeviceAndSwapChain에 의해 만들어지는데 크게 두 가지의 종류가 존재합니다. 하나는 immediate context이고 다른 하나는 deffered context입니다. 차이에 대해 설명을 해주긴 하는데 결론만 놓고 보면 Deffered context는 Multithreaded rendering을 위한 모델에서 Immediate Context와 함께 등장합니다.이 둘 모두 ID3D11DeviceContext interface로 implemented 된 상태입니다.

    자세한 정보가 여기저기 있습니다.

    Immediate context가 deffered context와 다른 차이점 중 하나에는 immediate context는 직접 Rendering API라든가 commands를 Device로부터 요청할 수 있다는 점입이다. Deffered Context는 D3D11에서 등장한 개념입니다. Chili가 자세히 설명을 해주지 않았지만 MSDN문서를 살펴보면 이 Deffered Context가 Complex Scene을 Concurrent task로 바꾸어 준다고 합니다. 이 문서도 읽어보는 편이 좋습니다. 사실 현시점에선 피상적으로밖에 이해할 수 없습니다. 아마 한 동안은 Deffered Context에 대해 신경을 쓰지 않아도 좋을 것 같습니다.

     

    'Graphics' 카테고리의 다른 글

    [18] - Debug Layer Diagnostics  (0) 2021.07.21
    [17] - Device Init  (0) 2021.07.20
    [15] - COM object  (0) 2021.07.19
    [14] - Vertex processing - 2  (0) 2021.07.17
    [13] - Vertex processing - 1  (0) 2021.07.15
Designed by Tistory.