OpenGL Buffer Object 그래픽스/렌더링


3D Application 은 항상 어떻게 하면 빠르게 그릴까를 연구해왔다.
Geometry 를 좀 더 빠른 속도로 그리기 위해 매번 새로운 기법들이 개발되어 왔는데.. OpenGL 1.1 시절에는 Display List 로 rendering command 를 미리 컴파일하여 binary 버퍼화해버리는 원시적인 방법이 사용됐다. 그러다가 동적인 Geometry 를 일반적인 방법으로 사용하기 위해 Vertex Array 를 사용했고, CVA(Compiled Vertex Array) 나 T&L 이 가능해 지면서 더욱 더 빠른 처리가 가능해졌다.

그 후에는 Vertex Array 자체를 Local(Video)/Non-local(AGP) 메모리에 상주시켜 GPU 가 직접 메모리를 access 하도록 하는 VAR/VAO/VBO 같은 확장이 추가되었다. 이 개념은 OpenGL 이나 DirectX 같은 API 보다는, 그래픽 하드웨어와 더 밀접한 관련이 있다고 볼 수 있는데... 하드웨어 입장에서는 몇가지 operation 으로 나눠볼 수 있겠다.

VBO 기준으로 설명하면..

a. 버퍼를 적당한 새로운 곳에 채운다 - BufferData (Video / AGP / System memory)
b. 버퍼의 내용을 버린다(Discard) - BufferData (data 를 NULL 로 세팅)
c. 버퍼의 장소를 유지한채 전체 버퍼를 synchronous 하게 포인터를 얻어온다 - MapBuffer / UnmapBuffer
d. 버퍼의 장소를 유지한채 일정 부분만 synchronous 하게 업데이트 한다 - BufferSubData

2008년에 와서 map_buffer_range 확장으로 좀 더 세밀하게 제어가 가능해졌는데..

버퍼의 일정 부분만 sync or async 하게 Map 이 가능하고,
업데이트시 flush 되는 sub range 를 별도로 지정이 가능해졌다.

보통 GPU 쪽에서 사용할땐 Video > AGP > System memory 순으로 빠르고,
CPU 를 경유한 write 는 System > AGP > Video memory 순으로 빠른데...
용도에 따라서 static 버퍼는 한번만 write 하면 그만이지만, dynamic 버퍼는 여러번 write 하게된다.
GPU 에서 버퍼를 점유중일때, 사용이 끝날때까지 기다리지 않고 asynchronous 하게 write 를 해야 속도를 올릴 수 있다.

※ 필자의 경험을 바탕으로 적은거라 일부 틀린 내용이 있을 수도 있음

다양한 extension 들이 추가되면서 이 buffer 를 아래와 같은 여러가지 데이터 형태로서 사용 할수 있게 되었다. (점점 범용적이 되어가고 있다.)

버퍼를 버텍스 데이터로 사용 --- VertexArrayPointer - ARB_vertex_buffer_object (NV10, R100)
프레임버퍼로/프레임버퍼로부터 버퍼를 쓰기 --- DrawPixels/ReadPixels - ARB_pixel_buffer_object (NV40, R300)
버퍼로부터 텍스쳐를 업데이트 --- TexSubImage - ARB_pixel_buffer_object ( '' )
버퍼로부터 쉐이더 상수를 지정 --- UniformBuffer - EXT_bindable_uniform (G80, R600)
버퍼를 커다란 1D 텍스쳐로 사용 --- TexBuffer - EXT_texture_buffer_object (G80, R600)

이정도만으로도 활용범위는 뭔가 굉장히 많아 보인다.

몇가지 예를 들면...

ex 1. Render To VertexBuffer

fragment shader 를 거쳐 나온 프레임버퍼를 비동기로 읽어 vertex array 로 재사용 가능

ex 2. 텍스쳐 스트리밍

텍스쳐를 화면에 그리면서 다음 프레임의 내용을 비동기로 업데이트 가능

ex 3. 하드웨어 스키닝에 활용

a) VTF(Vertex Texture Fetch) 를 이용해 텍스쳐 데이터로 전달시 PBO 를 이용해 텍스쳐를 업데이트
b) a 와 같은 방식으로 texture buffer object 를 이용해 버퍼를 텍스쳐 데이터로 직접 사용
c) bindable uniform 을 이용해 쉐이더 상수 버퍼를 구성후 쉐이더에 버퍼 형식으로 전달

참고 자료:
http://developer.nvidia.com/object/using_VBOs.html
http://www.songho.ca/opengl/gl_vbo.html
http://www.songho.ca/opengl/gl_pbo.html
http://winnwe.com/pda/perma/1115/
http://winnwe.com/pda/perma/1116/
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_vertex_array_range.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_vertex_array_range2.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_NV_pixel_data_range.txt
http://developer.download.nvidia.com/opengl/specs/GL_NV_transform_feedback.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_ARB_vertex_buffer_object.txt
http://www.nvidia.com/dev_content/nvopenglspecs/GL_ARB_pixel_buffer_object.txt
http://developer.download.nvidia.com/opengl/specs/GL_EXT_bindable_uniform.txt
http://developer.download.nvidia.com/opengl/specs/GL_EXT_texture_buffer_object.txt
http://www.opengl.org/registry/specs/APPLE/flush_buffer_range.txt
http://www.opengl.org/registry/specs/ARB/map_buffer_range.txt
http://www.opengl.org/registry/specs/ARB/copy_buffer.txt
http://www.opengl.org/registry/specs/ARB/uniform_buffer_object.txt

덧글

  • shint 2015/08/23 10:44 # 삭제 답글




    //
    사용자로써 글을 덧붙여 봅니다.

    - 전체화면은 60 FPS에 거의 고정 됩니다. D3DPRESENT_INTERVAL_IMMEDIATE 를 적용하면 200 FPS 정도가 나옵니다.
    - 윈도우모드는 3배 빠릅니다.

    - Glide3D 라는 Wrapper 프로그램으로 말씀하신 사항에 함수와 버퍼. 텍스처 메모리등에 기능을 조정 할 수 있었습니다.
    - OpenGL Viewer 라는 프로그램으로 OpenGL 버전을 확인할 수 있습니다.

    - NVIDIA 제어판에서 기본값으로 설정할 경우.
    DirectX SDK 의 Shadow Volume 400 x 300 크기에서 800 FPS 가 나오던것이. space bar 를 누르면. 2500 FPS 까지 나왔습니다.
    이것은 WinPorc() 에 사용 여부를 결정하는것입니다.

    - 그래픽 카드의 GPU 점유율이 없는데도 (혹은 낮은데도). 렌더링이 가능한 방법이 있습니다.
    ATI no texture memory causes low gpu usage and low FPS (텍스쳐 메모리 없는. GPU의 낮은 FPS 사용)
    https://www.youtube.com/watch?v=SVutrSrGfa8

    - 윈도우 10에는 사용자 지정 배율'기능이 있습니다.
    벡터 이미지로 아주 깨끗한 이미지로 확대가 됩니다.
    물론. 윈도우에는 EMF 벡터 이미지 파일 포맷이 있습니다.

    - DownSampling 이라는 용어를 알게 되었습니다.

    - 게임의 텍스쳐를 3840 x 2160 으로 하고. 1920 x 1080 화면으로 출력하면. 고속으로. 고품질에 영상을 얻을 수 있습니다.

    - 게임 텍스쳐가 클경우. 안티얼라이싱에 점유율이 높아져서 어려우니. 안티얼라이싱을 끄고. FXAA 를 켜는것이 게임성능과 보기에도 좋습니다.

    - 오버클락을 하게 될경우. FPS 와는 상관없이. 3D 온라인게임인 마영전이 2배속으로 가능하며. 30% 정도에 성능 향상이 있습니다.

    - Custom Shader 를 사용하게 되면. 해당 DirectX 를 사용하는 게임에 사용자가 Shdaer 효과를 적용할 수 있습니다.

    - OpenAL for FFMPEG 을 사용하면. EXT 공용 API를 활용해서. 영상 공유 및 녹화가 가능합니다.

    - 절전 모드에서도 훌륭한 성능이 가능합니다.

    - V-SYNC 를 사용하게 되면. IE 에서의 ActiveX 플래시의 로딩시간이 줄어듭니다.

    - .NET Framework 는 NGEN.exe EQI 로 어느정도 최적화가 가능합니다.



    //이와는 상관없는 이야기지만...

    - 최대절전모드와 VHD를 사용하게 되면. 윈도우 및 응용 프로그램에 순간 부팅이 가능하게 됩니다.

    - 전력선 통신이 가능합니다.



댓글 입력 영역