Graphics Programming

OpenGL 4.6 / GLSL 4.6 본문

Season 1/OpenGL

OpenGL 4.6 / GLSL 4.6

minseoklee 2017. 12. 31. 01:30

※ 이 글은 미완성입니다.

※ 혼동의 여지가 있는 용어는 그대로 적었습니다. 실제 코드와 관련된 경우 영어 단어를 그대로 쓴 것도 있습니다.


목표: 절대로 다 번역하지 못한다. 쭉 훑어보면서 핵심만 번역하고 4.5와의 차이에 집중



OpenGL 4.6 Core: https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf

GLSL 4.6: https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.pdf


OpenGL 4.6 Core 목차

  1. 서문
    1. OpenGL 명세서의 서식
    2. OpenGL 그래픽스 시스템이란 무엇인가
    3. 관련 API
    4. 버그 리포트 작성
  2. OpenGL 기초
    1. 실행 모델
    2. 커맨드 신택스
      1. 스테이트 설정 커맨드를 위한 데이터 변환
      2. 스테이트 쿼리 커맨드를 위한 데이터 변환
    3. 커맨드 실행
      1. 오류
      2. 그래픽스 리셋 복구
      3. flush와 finish
      4. 수치 표현과 계산
      5. 고정점 데이터 변환
    4. 렌더링 커맨드
    5. 컨텍스트 스테이트
      1. 일반화된 컨텍스트 스테이트 쿼리
    6. 개체와 개체 모델
      1. 개체 관리
      2. 버퍼 개체
      3. 셰이더 개체
      4. 프로그램 개체
      5. 프로그램 파이프라인 개체
      6. 텍스처 개체
      7. 샘플러 개체
      8. 렌더버퍼 개체
      9. 프레임버퍼 개체
      10. 버텍스 배열 개체
      11. 트랜스폼 피드백 개체
      12. 쿼리 개체
      13. 싱크 개체
  3. 데이터플로우 모델
  4. 이벤트 모델
    1. 싱크 개체와 펜스
      1. 싱크 개체를 기다리기
      2. 시그널링
      3. 싱크 개체 쿼리
    2. 쿼리 개체와 비동기 쿼리
      1. 쿼리 개체 타입과 타겟
      2. 쿼리 개체 생성과 활성화
      3. 쿼리 개체 쿼리
    3. 타임 쿼리
  5. 공유 개체와 다중 컨텍스트
    1. 개체 삭제 비헤이비어
      1. 공유 컨텍스트 파괴의 사이드 이펙트
      2. 제거된 개체의 자동 언바인딩
      3. 제거된 개체와 개체 이름 생명주기
    2. 싱크 개체와 다중 컨텍스트
    3. 변경사항을 개체들에 전파하기
      1. 변경의 완료를 한 개체에 알리기
      2. 정의
      3. 규칙
  6. 버퍼 개체 (너무 길어서 이 밑으로 하위 목차는 생략)
  7. 프로그램과 셰이더
  8. 텍스처와 샘플러
  9. 프레임버퍼와 프레임버퍼 개체
  10. 버텍스 명세와 드로잉 커맨드
  11. 프로그래머블 버텍스 프로세싱
  12. (코어 프로필과 무관한 내용이라 생략)
  13. 고정 기능 버텍스 포스트 프로세싱
  14. 고정 기능 프리미티브 어셈블리와 래스터화
  15. 프로그래머블 프래그먼트 프로세싱
  16. (코어 프로필과 무관한 내용이라 생략)
  17. 프래그먼트와 샘플을 프레임버퍼에 기록하기
  18. 픽셀 읽기와 복사
  19. 컴퓨트 셰이더
  20. 디버그 출력
  21. 특수 함수들
  22. 컨텍스트 스테이트 쿼리
  23. 스테이트 테이블

부록

  1. 불변식
  2. Corollaries
  3. OpenGL SPIR-V 실행 환경
  4. 압축 텍스처 이미지 포맷
  5. 프로필과 deprecation 모델
  6. 버전 4.2
  7. 버전 4.3
  8. 버전 4.4
  9. 버전 4.5
  10. 버전 4.6
  11. OpenGL 레지스트리, 헤더 파일, ARB 확장


Chapter 1

서문

앞으로 이 문서를 "OpenGL 명세서" 또는 "명세서"라고 칭하며, OpenGL 그래픽스 시스템을 서술한다. OpenGL이 무엇이고, 어떻게 작동하고, 구현하려면 무엇이 필요한가?


OpenGL 4.3부터 프로그래머블 셰이딩에 집중하기 위해 많은 구조가 변경되었다.


OpenGL("Open Graphics Library"를 뜻함)은 그래픽스 하드웨어에 대한 API(Application Programming Interface)이다. 이 API는 고품질 이미지, 특히 3차원 물체들의 컬러 이미지를 생산하기 위해 프로그래머가 셰이더 프로그램, 개체, 오퍼레이션을 기술할 수 있게 하는 프로시저와 함수 수천 개로 이루어진다.


OpenGL을 사용하는 프로그램은 대개 윈도우를 열고 무언가를 그릴 프레임버퍼를 만드는 것으로 시작한다. 그 다음 OpenGL 컨텍스트를 할당하고 윈도우와 연결한다. 그 다음 셰이더, 지오메트리, 텍스처를 정의하는 OpenGL 커맨드를 실행하고 일부 지오메트리를 셰이더에 전달해 지오메트리를 그린다. 드로잉 커맨드는 점, 선분, 폴리곤 같은 간단한 기하 물체를 기술하며, 후에 셰이더에 의해 변형된다. 픽셀 읽기 및 쓰기를 통해 프레임버퍼를 직접 제어하는 커맨드도 있다.


한 명세서 버전에서 deprecated 표시된 피처는 다음 버전에서 제거될 계획이다. deprecation 모델은 부록 E에서 더 자세히 설명한다.


OpenGL과 연관된 다른 API들로 OpenGL Shading Language, OpenGL ES, OpenGL ES Shading Language, SPIR-V, WebGL, 윈도우 시스템 바인딩(GLX, WGL, MacOs X 윈도우 시스템 바인딩, EGL), OpenCL이 있다.


SPIR-V는 OpenCL, OpenGL, Vulkan 등 여러 Khronos API를 위한, 그래픽 셰이더 스테이지 및 컴퓨트 커널을 표현하는 바이너리 중간 언어다. SPIR-V 명세서 그리고 OpenGL Shading Language 명세서를 위한 SPIR-V 확장은 Khronos API Registry에서 볼 수 있다.


OpenGL은 그래픽스 컨텍스트, 렌더링에 쓸 윈도우, 이 명세서의 범위를 벗어난 리소스들을 생성 및 관리하는 보조 API가 있어야 한다. 운영체제와 윈도우 시스템마다 그런 API를 제공한다.

  • GLX는 X Windows System에서 OpenGL을 위한 API이다. 주로 리눅스와 유닉스 시스템을 겨냥한 것이지만 마이크로소프트 윈도우즈, MacOS X 등에서도 GLX 구현이 존재한다. GLX 명세서는 OpenGL Registry에서 볼 수 있다.
  • WGL은 마이크로소프트 윈도우즈를 위한 API이다. 마이크로소프트의 MSDN에 문서화되어있지만, 완벽한 명세서는 존재하지 않는다.
  • MacOS X 윈도우 시스템인 Quartz에서 OpenGL을 지원하기 위한 API는 CGl, AGL, NSOpenGLView 등 여러 가지가 있다. 이 API들은 애플의 개발자 웹사이트에 문서화 되어있다.
  • EGL은 모바일과 임베디드 장치에서 OpenGL ES를 위한 API이다. 몇 데스크탑 플랫폼에는 OpenGL을 지원하는 EGL 구현이 있다. EGL 명세서는 Khronos API Registry에서 볼 수 있다.

OpenCL은 개인 컴퓨터, 서버, 모바일 장치 등에 있는 프로세서들(GPU 포함)에서 크로스 플랫폼, 범용 병렬 프로그래밍을 위한 공개된, 로열티 없는 표준이다. OpenCL은 OpenCL 메모리와 이미지 개체를 그에 대응하는 OpenGL 버퍼와 텍스처 개체와 공유하고, OpenCL과 OpenGL간 데이터 제어 및 전송을 조절하기 위한 interop 메서드를 정의한다. 이로 인해 애플리케이션이 데이터 처리를 OpenCL과 OpenGL로 분리할 수 있다. 예를 들어, OpenCL로는 물리 모델을 구현하고 OpenGL로는 렌더링을 할 수 있다. OpenCL 명세서는 Khronos API Registry에서 볼 수 있다.




Chapter 2

OpenGL 기초


OpenGL 실행 모델, API 문법, 컨텍스트와 쓰레드, 수치적 표기, 컨텍스트 스테이트와 스테이트 쿼리, 여러 종류의 개체와 셰이더 등 기본적인 개념들을 소개.


OpenGL은 GPU 메모리의 데이터 처리, 프레임버퍼에 렌더링, 프레임버퍼의 값 읽기만 처리. 다른 입출력 장치는 없다.


GL은 여러 셰이더 프로그램과 컨텍스트 스테이트에 의해 재어되는 고정 기능 처리 유닛들을 써서 프리미티브(primitive)를 그린다. 각 프리미티브는 점, 선분, 패치, 폴리곤 중 하나다. 컨텍스트 스테이트는 독립적으로 변경된다. 한 스테이트를 설정하는 것은 다른 상태에 영향을 주지 않는다. (하지만 모든 스테이트와 셰이더는 서로 상호작용해서 프레임버퍼의 최종 결과물을 결정한다) 스테이트를 설정하고 프리미티브를 그리면 다른 GL 오퍼레이션들은 함수 또는 프로시저 호출의 형태인 커맨드 전달으로 서술된다.


프리미티브는 하나 이상의 정점(vertex; 복수형: vertices)으로 정의된다. 정점은 점, 선분의 끝, 폴리곤의 모서리를 정의한다.


커맨드들은 항상 전달된 순서대로 처리된다. 커맨드의 영향이 나타나기 전에 중간 지연이 있을 수 있다. 이는 예를 들어 한 프리미티브를 완전히 그린 다음에 프레임버퍼에 영향을 주는 후속 커맨드를 실행해야 한다는 뜻이다. 또한 쿼리와 픽셀 읽기 오퍼레이션은 이전의 모든 GL 커맨드를 완료해야 일관된 상태를 얻는다. 일반적으로 GL 스테이트 또는 프레임버퍼에 대한 GL 커맨드의 영향은 후속 커맨드가 영향을 끼치기 전에 완료되어야 한다.


호출에서 데이터 바인딩이 일어난다. GL 커맨드에 전달된 데이터는 그 커맨드가 도착할 때 해석된다. 커맨드가 데이터에 대한 포인터를 요구하더라도 그 데이터는 호출이 발생할 때 해석되고, 이후 그 데이터의 변화는 GL에 영향을 주지 않는다. (후속 커맨드에서 동일 포인터를 사용하지 않는 한)


GL 커맨드 해석은 클라이언트-서버 모델을 따른다. 프로그램(클라이언트)은 커맨드를 발생시키고, 커맨드는 GL(서버)에 의해 해석 및 처리된다. 서버는 클라이언트와 같은 주소 공간에 있을 수도, 아닐 수도 있다. 그런 의미에서 GL은 네트워크 투명하다(network transparent). 서버는 여러 GL 컨텍스트를 가질 수 있고, 각각은 현재 GL 상태와 개체의 캡슐화다. 클라이언트는 컨텍스트들 중 하나를 현재(current) 컨텍스트로 선택할 수 있다.


프로그램이 현재 컨텍스트가 아닌 것에 GL 커맨드를 발행할 때의 결과는 정의되지 않은 동작(undefined behavior)이다.


프레임버퍼는 두 종류가 있다. 현재 컨텍스트와 연관되는, 윈도우 시스템이 제공하는 프레임버퍼와 애플리케이션이 생성한 프레임버퍼다. 윈도우 시스템이 제공하는 프레임버퍼는 디폴트 프레임버퍼(default framebuffer)라 한다. 애플리케이션이 생성한 프레임버퍼는 프레임버퍼 개체(framebuffer object)라 하며 원할 때 생성할 수 있다. 한 컨텍스트에 대해 두 프레임버퍼를 읽기, 그리기 오퍼레이션에 연결할 수 있다. 디폴트 프레임버퍼와 프레임버퍼 개체는 상태를 설정, 관리하는 인터페이스에 의해 구분된다.


디폴트 프레임버퍼에 대한 GL 커맨드의 결과는 결국 윈도우 시스템에 의해 제어된다. GL 컨텍스트를 초기화하거나 디폴트 프레임버퍼를 구성하는 GL 커맨드는 없다. 프레임버퍼 내용을 물리적인 디스플레이 장치에 표시하는 것도 GL의 소관이 아니다.


디폴트 프레임버퍼의 할당과 구성은 GL의 바깥, 1.3.6절에서 서술한 보조 API들에 의해 처리된다.


모든 렌더링을 프레임버퍼 개체에 해야 할 경우, 디폴트 프레임버퍼 없이 GL 컨텍스트를 사용할 수 있다. 이것은 오프스크린 렌더링(offscreen rendering)이 필요한 애플리케이션에 유용하다.


커맨드 이름, 상수, 타입들은 C 언어의 OpenGL 바인딩과 같이 전치사가 붙는다(gl, GL_, GL). 이는 다른 패키지들과 이름 충돌을 피하기 위함이다. 이 문서에서는 명확하기 때문에 전치사들을 생략한다.


이 명세서는 OpenGL 커맨드들을 ANSI C 문법을 이용해 함수 또는 프로시저로 서술한다.


여러 GL 커맨드가 같은 연산을 수행하지만 전달받는 인자는 다르다. GL 커맨드는 이름(name)으로 시작하고, 커맨드에 따라 매개변수를 서술하는 문자들이 붙을 수 있다. 그런 경우, 숫자는 지시 타입의 값 개수를 나타낸다. 그 다음 표 2.1의 타입 서술자(descriptor) 중 하나가 붙는데, 매개변수의 크기와 데이터 타입을 나타낸다. 마지막으로 v가 붙는다면 개별 인자가 아니라 값의 배열에 대한 포인터를 받는다는 뜻이다.


void Uniform4f( int location, float v0, float v1, float v2, float v3 );

void GetFloatv( enum pname, float *data );


다음은 커맨드 선언의 일반적인 형태다.


rtype Name{1234}{ b s i i64 f d ub us ui ui64}{v} ( [args ,] T arg1, . . ., T argN [, args] );


GL 타입은 C 타입이 아니다. GL 타입 int는 이 문서 밖에서는 GLint로 칭해지며, C의 int 타입과 동등하지 않을 수 있다.


스테이트 설정 커맨드에 대한 데이터 변환

  • 내부 상태의 타입이 진위값일 때, 정수 0 또는 부동소수점 값 0은 FALSE로, 그 외는 TRUE로 변환된다.
  • 내부 상태의 타입이 정수 또는 열거형일 때, 진위값 FALSE와 TRUE는 0과 1로 변환된다. 부동소수점 수는 가장 가까운 정수로 떨어진다. 결과값이 내부 상태 변수에 담을 수 없을 만큼 클 때, 내부 상태 값은 정의되지 않는다.
  • 내부 상태의 타입이 부동소수점 수일 때, 진위값 FALSE와 TRUE는 0.0과 1.0으로 변환된다. 정수는 부동소수점 수로 변환되는데, 정규화 여부는 커맨드마다 다르다.

이 명세서에서는 대부분 하나의 CPU 쓰레드에 바인딩된 하나의 컨텍스트의 동작을 논의한다. 여러 컨텍스트가 GL 개체들을 공유하고, 컨텍스트마다 서로 다른 쓰레드에 바인딩되는 것도 가능한 일이다. 오류 보고, 커맨드 큐 비우기(flushing), 커맨드 스트림간 동기화를 사용하면 GPU를 최적화하고, 느슨하게 엮인 작업들을 여러 컨텍스트로 나누어서 GPU를 더 잘 활용할 수 있다.


CPU 쓰레드를 생성, 관리, 파괴하는 방법은 호스트 CPU 운영체제가 정의하지 이 명세서의 소관이 아니다. GL 컨텍스트를 CPU 쓰레드에 바인딩하는 것은 1.3.6절에서 서술한 윈도우 시스템 바인딩 레이어에서 제어한다.


GL은 오류로 간주할 법한 상황들 중 일부만을 오류라고 감지한다. 많은 경우 오류 검사는 오류가 없는 프로그램의 퍼포먼스에 크게 영향을 주기 때문이다.


enum GetError( void );


이 명령으로 오류 정보를 얻는다. 감지 가능한 오류마다 숫자 코드를 배정받는다. 오류를 감지하면 플래그가 설정되고 그 코드는 기록된다. 이후 일어나는 오류는 이 기록된 코드에 영향을 주지 않는다. GetError를 호출하면 그 코드가 반환되고 플래그는 클리어되며, 그 다음 일어나는 오류의 코드가 기록될 것이다. GetError를 호출했는데 NO_ERROR가 반환되면 마지막 GetError 호출 이후(또는 GL 초기화 이래로) 아무 오류도 감지되지 않은 것이다.


분산 구현을 위해 여러 플래그-코드 쌍이 있을 수 있다. 이 경우 GetError가 NO_ERROR 외의 값을 반환하고 나서도 연이은 GetError 호출이 0이 아닌 코드를 명시되지 않은 순서로 반환할 수 있으며, 이는 NO_ERROR 외의 모든 코드를 반환할 때까지 계속된다. NO_ERROR가 아닌 오류 코드가 더이상 없으면 모든 플래그가 리셋된다.


표 2.3은 GL 오류들을 요약한 것이다. 현재로선 오류 플래그가 설정되었을 때 GL 오퍼레이션의 결과가 미정인 것은 OUT_OF_MEMORY 오류가 발생했을 때 뿐이다. 다른 경우에는 따로 언급하지 않는 한 사이드 이펙트가 없다. 오류를 발생시키는 커맨드는 무시되고 GL 스테이트나 프레임버퍼 내용에 아무 영향을 주지 않는다. 그런 커맨드가 값을 반환하면, 역시 따로 언급하지 않는 한 그 값은 0이다. 그런 커맨드가 포인터 인자를 통해 값을 수정하는 커맨드일 경우, 아무 것도 변경되지 않는다.


몇 가지 오류 발생 조건은 모든 GL 커맨드 호출에 해당한다.

  • 이전 GL 커맨드의 결과로 GL 컨텍스트가 리셋되었거나 어떤 커맨드 실행의 사이드 이펙트로 컨텍스트가 리셋되었으면 CONTEXT_LOST 오류가 발생한다.
  • 열거형 값을 요구하는 커맨드가 허용되지 않는 기호 상수를 받을 경우, INVALID_ENUM 오류가 발생한다. 그 인자가 기호 상수에 대한 포인터여도, 포인터가 가리키는 값(들)이 그 커맨드에 허용되지 않는 경우에도 마찬가지다. 어떤 경우에는 커맨드에 기호 상수를 사용할 수 있지만, 현재 GL 스테이트나 그 커맨드의 다른 인자에 전달된 값과 같이 쓰는 것은 금지된다. 이런 경우는 문서에 명시되며, INVALID_OPERATION 오류가 발생한다.
  • 인자 타입이 sizei 또는 sizeiptr인데 음수를 전달하면 INVALID_VALUE 오류가 발생한다.
  • 커맨드 실행의 사이드 이펙트로 메모리가 바닥나면 OUT_OF_MEMORY 오류가 발생할 수 있다.
커맨드가 여러 오류를 발생시킬 수 있는 경우, GL 구현은 그 중 아무거나 발생시켜도 괜찮다.

오류가 발생하면 GL은 그 원인을 설명하는 디버그 출력 메시지도 생성할 수 있다. (20장 참조) 그 메시지의 소스는 DEBUG_SOURCE_API, 타입은 DEBUG_TYPE_ERROR이며, ID는 구현에 따라 다르다.


어떤 커맨드에 대해 오류가 발생했지만 원인이 그 커맨드가 아닌 경우도 있다. 예시로 디퍼드 프로세싱을 하는 셰이더 프로그램에서는 버텍스 명세 커맨드를 이용해 프리미티브를 그리려 할 때가 되어서야 링크 오류가 발생하는 경우가 있다. 그런 경우 오류는 그 커맨드가 아니라 명세서의 다른 어딘가에 서술되어 있을 것이다.


no error 모드를 활성화하고 GL 컨텍스트를 생성하면 드라이버가 오류를 발생시켰어야 할 곳에서 미정의 동작이 발생한다. 이는 애플리케이션 종료에 영향을 줄 수 있다. GetError 호출은 항상 NO_ERROR 또는 OUT_OF_MEMORY를 반환한다.


특정 사건에 의해 GL 컨텍스트가 리셋될 수 있다. 그런 사건이 일어난 컨텍스트를 소실된 컨텍스트(lost context)라 하며 거의 어떤 것에도 쓸 수 없다. 회복하려면 새 컨텍스트를 만들고 소실 컨텍스트로부터 모든 관련 스테이트를 재생성해야 한다. 다음 함수는 그래픽스 리셋 스테이트의 현재 상태를 반환한다.


enum GetGraphicsResetStatus( void );


  • NO_ERROR는 GL 컨텍스트가 마지막 호출 이후 리셋 스테이트가 되지 않았음을 나타낸다.
  • GUILTY_CONTEXT_RESET은 현재 GL 컨텍스트의 원인일 수 있는 리셋을 감지했음을 나타낸다.
  • INNOCENT_CONTEXT_RESET은 현재 GL 컨텍스트와 무관한 리셋을 감지했음을 나타낸다.
  • UNKNOWN_CONTEXT_RESET은 원인 불명의 그래픽스 리셋을 감지했음을 나타낸다.
리셋 알림 동작은 컨텍스트 생성 시간에 결정되며 GetIntegerv를 pname = RESET_NOTIFICATION_STRATEGY로 호출해서 쿼리할 수 있다. 동작이 NO_RESET_NOTIFICATION이면 GL 구현체는 리셋 이벤트를 절대 알려주지 않고, GetGraphicsResetStatus는 항상 NO_ERROR를 반환할 것이다.

그래픽스 리셋이 발생한 컨텍스트에서는 이후 GL 커맨드들이 CONTEXT_LOST 오류를 발생시킨다. 이런 커맨드들은 사이드 이펙트가 없으며 무기한 블록되거나 애플리케이션 종료를 일으키지 않는다.
* 예외 상황은 원문 참조


구현체는 여러 커맨드를 커맨드 큐에 쌓아두고 GL 구현체에 한꺼번에 전송할 수 있다. Flush 커맨드는 이전에 발행된 모든 GL 커맨드가 유한 시간 안에 완료되도록 한다. (하지만 이 커맨드들은 Flush 반환 후에도 실행 중일 수 있다)


void Flush( void );


Finish 커맨드는 이전에 발행된 모든 GL 커맨드가 완료되도록 강제한다. Flush는 커맨드들의 영향이 GL 클라이언트와 서버 스테이트, 프레임버퍼에 전부 적용될 때까지 반환되지 않는다.


void Finish( void );


GL은 실행 도중 많은 부동소수점 연산을 수행해야 한다. GL 구현체는 아래의 "FLoating-Point Computation"에 정의된 범위와 정밀도 요구사항을 만족해야 한다. 이 요구사항들은 셰이더 실행 외의 GL 오퍼레이션에서 수행되는 계산에만 적용된다. 셰이더 실행 도중의 요구사항은 다르며 OpenGL Shading Language Specification에 기술되어 있다.

* Floating-Point Computation, 16비트 부동소수점 수, 부호 없는 11비트 부동소수점 수, 부호 없는 10비트 부동소수점 수, 고정소수점 계산 생략. 원문 참조


제너릭 버텍스 속성(attribute), 픽셀 색상, 깊이 성분이 정수로 표현될 때는 대개 정규화되었다고 한다. 정규화된 정수는 부동소수점 수로 변환하거나 부동소수점 수로부터 변환될 때 특별하게 취급되며 정규화된 고정소수점 수라고 칭한다. 그런 값들은 항상 부호가 있거나 부호가 없다.

* 이하 생략. 원문 참조


2.4 렌더링 커맨드

프레임버퍼에 렌더링을 수행하는 GL 커맨드들은 렌더링 커맨드라고 부르며 드로잉 커맨드 *Draw* 들(10.4절)과 다음 커맨드들을 포함한다.

  • BlitFramebuffer (18.3.1절)
  • Clear (17.4.3절)
  • ClearBuffer* (17.4.3.1절)
  • DispatchCompute* (19절)
2.5 컨텍스트 스테이트
컨텍스트 스테이트는 클리핑, 프리미티브 래스터화, 프레임버퍼 클리어 등 GPU의 고정 기능 스테이지를 제어하고, 개체들의 바인딩(binding) 즉 커맨드 실행 도중 어떤 개체들이 사용되는 지를 기술한다.

컨텍스트 스테이트에는 GL 서버에 있는 서버 스테이트(server state)와 GL 클라이언트에 있는 클라이언트 스테이트(client state)가 있다. 대부분은 서버 스테이트다. 따로 명시하지 않으면 모든 스테이트는 서버 스테이트다. 각각의 컨텍스트 인스턴스는 완전한 서버 스테이트 모음을 가진다. 각각의 클라이언트로부터 서버로의 커넥션은 완전한 클라이언트 스테이트 모음을 가진다.

컨텍스트 스테이트 쿼리들은 22장에서 자세히 설명한다.

2.6 개체와 개체 모델

개체 타입마다 이름 공간(name space)를 가진다. 개체들의 이름은 uint 타입의 부호 없는 정수로 표현된다. 이름 0은 GL에 의해 예약되어 있다. 어떤 타입에서는 0이 그 타입의 기본 개체(default object)의 이름이고, 어떤 타입에서는 0이 어떠한 실제 인스턴스와도 일치하지 않는다.


대부분의 타입에서 개체의 이름 생성은 Gen으로 시작하고 개체 타입이 따라오는 커맨드를 사용해 쓰이지 않는 이름을 생성하여 이루어진다. 커맨드 GenBuffers는 쓰이지 않고 있던 버퍼 개체 이름을 하나 이상 반환한다.


당장 생성된 이름은 개체 인스턴스에 대응하지 않는다. 해당 이름을 가지는 개체는 그 이름을 컨텍스트에 바인딩해서 생성한다. 예를 들어 버퍼 개체는 GenBuffers가 반환한 이름을 가지고 BindBuffer를 호출하여 생성된다. BindBuffer는 버퍼 개체와 그 개체의 상태를 위한 리소스를 할당하고 이름과 개체를 연관짓는다.


막 초기화된 개체를 나타내는 새 이름(들)을 반환하는 함수를 통해 개체를 직접 생성할 수도 있다. CreateProgram과 FenceSync, CreateBuffers, CreateTextures, CreateVertexArrays가 그 예다.


개체 타입에 고유한 삭제 커맨드를 호출하여 해당 개체를 제거한다. DeleteBuffers 커맨드는 삭제할 버퍼 개체들의 이름 배열을 받는다. 개체를 삭제하면 내용물이 사라지고 그 이름은 이름 생성에 다시 쓸 수 있다. 이름 생성에 쓰였지만 개체에 대응하지 않는 이름을 삭제하면 미사용 상태로 된다. 미사용 이름 또는 이름 0을 삭제하는 시도는 무시된다.


개체를 삭제했지만 GL 컨텍스트가 쓰고 있는 중이면 그 이름은 즉시 미사용으로 되고 몇 타입의 개체들이 자동으로 현재 컨텍스트의 바인딩 포인트에서 언바인드된다. (5.12절) 하지만 실제 기저의 개체들은 더 이상 쓰이지 않을 때까지는 삭제되지 않는다. (5.1.3절)


여러 컨텍스트가 어떤 서버 스테이트를 공유할 수 있다. 이러한 공유는 윈도우 시스템 바인딩 API를 통해 이루어진다. (1.3.6절) 공유 개체는 5장에서 자세히 다룬다.


버퍼 개체는 데이터 스토어(data store)를 포함한다. 데이터 스토어는 서버 메모리의 고정 크기 할당을 보관하며, 그 메모리를 할당, 초기화, 읽고 쓰는 메커니즘을 제공한다. 데이터 스토어를 클라이언트와 서버가 공유할 수도 있으며, 동시에 접근할 수도 있다. (6장)


GL이 정의하는 프로그래머블 스테이지 중 하나를 실행하는 셰이더 프로그램의 일부 또는 전체를 나타내는 소스 코드 및 바이너리 코드는 하나 이상의 셰이더 개체로 캡슐화된다. (7장)


GL의 프로그래머블 스테이지에 쓰이는 셰이더 개체들은 서로 링크되어 프로그램 개체(program object)를 형성한다. 프로그래머블 스테이지들이 실행하는 셰이더 프로그램을 executable이라고 부른다. 각 executable을 정의하는 데 필요한 모든 정보는 프로그램 개체 안에 캡슐화된다. (7장)


프로그램 파이프라인 개체는 각 프로그래머블 스테이지에 대한 별도의 프로그램 개체 바인딩 포인트를 포함한다. 각 셰이더 오퍼레이션 조합마다 한 프로그램 개체를 쓰는 대신, 각 프로그래머블 스테이지마다 독립적인 프로그램으로 프리미티브를 처리하는 게 가능하다. 여러 셰이더를 다양하게 조합할 때 프로그램 개체보다 유연하다. 프로그램 파이프라인 개체는 프로그램 개체들에 대한 참조를 포함하는 컨테이너 개체로서 공유되지 않는다. (7장)


텍스처 개체 또는 텍스처는 이미지 요소들의 배열로부터 형성된 텍스처 이미지들의 모음을 포함한다. 이미지 요소들은 텍셀(texel)이라 칭한다. 텍스처 타입들은 8장 도입부에서 설명한다. 셰이더는 텍스처 좌표가 나타내는 텍스처 위치를 샘플할 수 있다. 샘플링의 세부사항은 그 텍스처의 샘플러 스테이트가 결정한다. (8장)


샘플러 개체는 셰이더가 텍스처를 읽을 때 샘플링이 어떻게 수행되는 지를 제어하는, 텍스처 개체 상태의 하위집합을 포함한다. 샘플러 개체와 텍스처 개체는 함께 바인딩될 수 있으며, 샘플러 개체 스테이트가 대응하는 텍스처 개체 스테이트를 덮어쓴다. (8장)


렌더버퍼 개체(renderbuffer object)는 무언가를 렌더링할 수 있는 포맷의 단일 이미지를 포함한다. 렌더버퍼 개체는 오프스크린 렌더링을 할 때 프레임버퍼 개체에 어태치된다. (9장)


프레임버퍼 개체(framebuffer object)는 색상, 깊이, 스텐실 버퍼를 포함해 프레임버퍼의 스테이트를 캡슐화한다. 그런 버퍼들은 각각 프레임버퍼 개체에 어태치된 렌더버퍼 개체 또는 텍스처 개체로 표현된다. 프레임버퍼 개체는 렌더버퍼 개체 또는 텍스처 개체에 대한 참조를 포함하는 컨테이너 개체이며 공유되지 않는다. (9장)

※ GL_EXT_framebuffer_object 확장이 정의하는 커맨드로 생성한 프레임버퍼 개체는 공유되지만 OpenGL 코어 또는 GL_ARB_framebuffer_object 확장이 정의하는 커맨드로 생성한 FBO는 공유되지 않는다. EXT 커맨드로 생성한 FBO를 비EXT 인터페이스를 통해 사용하거나 그 반대로 하는 경우 결과는 정의되지 않는다.


버텍스 어레이 개체(vertex array object)는 버텍스 애트리뷰트(attribute)들의 집합들의 모음이다. 각 집합은 버퍼 개체 데이터 스토어 안에 배열 형태로 저장된다. 이 배열의 원소들은 명시된 포맷과 컴포넌트 개수를 가진다. 현재 바인딩된 버텍스 어레이 개체의 애트리뷰트들은 드로잉 커맨드를 실행할 때 버텍스 셰이더의 입력으로 쓰인다. 버텍스 어레이 개체는 버퍼 개체에 대한 참조를 포함하는 컨테이너 개체이며 공유되지 않는다. (10장)


트랜스폼 피드백 개체(transform feedback object)는 트랜스폼 피드백 모드가 활성화되었을 때 트랜스폼 피드백 스테이지에 전달된, 변형된 프리미티브의 정점들의 애트리뷰트들을 포착하는 데 쓰인다. 트랜스폼 피드백에 필요한 스테이트, 애트리뷰트들을 포착해 넣을 버퍼 개체들에 대한 참조를 포함한다. 트랜스폼 피드백 개체는 컨테이너 개체며 공유되지 않는다. (13.2.1절)


쿼리 개체(query object)는 일련의 GL 커맨드 처리에 대한 정보를 반환한다. (드로잉 커맨드가 처리한 프리미티브 개수, 트랜스폼 피드백 버퍼에 기록된 프리미티브 개수, 프래그먼트 처리 중 깊이 테스트를 통과한 샘플 수, 커맨드 처리에 걸린 시간 등) 쿼리 개체는 공유되지 않는다. (4.2절)


싱크 개체(sync object)는 동기화 원시형(synchronization primitive)으로서 작동한다. 이것은 완료 상태를 검사하거나 기다릴 수 있는 사건의 표현이다. 싱크 개체는 GL 상태 기계 또는 그래픽스 파이프라인에서 발생하는 오퍼레이션들 간의 동기화에 쓰거나 여러 그래픽스 컨텍스트 사이를 동기화하는 데 쓸 수 있다. 싱크 개체는 공유 가능하다. (4.1절)


디스플레이 리스트(display list)는 코어에 포함되지 않으며 호환 프로필에서만 정의된다.




3장

데이터플로우 모델

그림 3.1은 GL의 블록 다이어그램이다.



어떤 커맨드는 지오메트리 개체를 그리고 어떤 커맨드는 여러 스테이지에서 개체들을 어떻게 다룰 지를 제어하는 스테이트를 설정하고, 어떤 것은 텍스처 개체나 버퍼 개체에 포함되는 데이터를 기술한다. 커맨드들은 프로세싱 파이프라인으로 전송된다.


그림의 순서는 GL을 서술하는 용도일 뿐이며 GL이 어떻게 구현되어야 하는 지를 강제하는 규칙이 아니다.




4장

이벤트 모델

싱크 개체는 스테이터스 값 signaled 또는 unsignaled를 가진다. 이벤트들은 싱크 개체에 연관된다. 싱크 개체가 생성되면 스테이터스는 unsignaled다. 연관된 이벤트가 발생하면 싱크 개체의 스테이터스는 signaled로 된다. GL은 싱크 개체가 signaled될 때까지 대기할 것을 요청할 수 있다.


처음에는 펜스 싱크 개체(fence sync object)라는, 한 타입의 싱크 개체만 정의된다. 연관된 이벤트는 GL 커맨드 스트림에 펜스 커맨드가 놓일 때 발생한다. 펜스 싱크 개체는 GL 커맨드 스트림의 일부가 완료되는 것을 기다리는 데 쓰이며, Finish의 보다 유연한 형태라고 할 수 있다.


sync FenceSync( enum condition, bitfield flags );


이 커맨드는 새 펜스 싱크 개체를 생성하고 GL 커맨드 스트림에 펜스 커맨드를 넣은 다음, 생성된 싱크 개체와 연관시킨다. 반환값은 싱크 개체에 대응하는, 0이 아닌 이름이다.


펜스 커맨드에 의해 condition이 만족되면 싱크 개체는 시그널되고, sync를 기다리던 ClientWaitSyncWaitSync 커맨드가 언블록된다.


FenceSync로 생성한 싱크 개체의 초기 값

 속성 이름

 속성 값

 OBJECT_TYPE

 SYNC_FENCE

 SYNC_CONDITION

 condition

 SYNC_STATUS

 UNSIGNALED

 SYNC_FLAGS

 flags


FenceSync의 오류 상황: 원문 참조


void DeleteSync( sync sync );


싱크 개체는 DeleteSync로 제거한다. sync와 연관된 펜스 커맨드가 완료되었거나 sync를 기다리는 ClientWaitSync 또는 WaitSync 커맨드가 없으면 sync가 즉시 제거된다. 그렇지 않으면 삭제 후보가 되어, 연관된 펜스 커맨드가 없고 대기 중인 ClientWaitSync 또는 WaitSync 커맨드가 없는 때가 되어야 제거된다.


비동기 쿼리(asynchronous query)는 일련의 GL 커맨드의 처리에 대한 정보를 반환하는 메커니즘을 제공한다. GL이 제공하는 쿼리의 종류로는 프리미티브 쿼리, 트랜스폼 피드백 오버플로우 쿼리, 오클루전 쿼리, time elapsed 쿼리, timer 쿼리, sumission 쿼리, 셰이더 쿼리, 프리미티브 클리핑 쿼리가 있다. 원문 참조


비동기 쿼리의 결과는 집합 내 마지막 커맨드가 완료되는 즉시 GL에 의해 반환되는 것이 아니다. 쿼리 결과가 완성되지 않은 도중에도 후속 커맨드들이 처리될 수 있다. 쿼리 결과가 접근 가능해지면 연관된 쿼리 개체에 저장된다. 4.2.3절에서 서술하는 커맨드들은 쿼리 결과가 언제 접근 가능한 지를 결정하는 메커니즘을 제공하며, 쿼리의 실제 결과를 반환한다. 쿼리 개체들의 이름공간은 부호 없는 정수로서 0은 GL에 의해 예약되어 있다.


void GenQueries( sizei n, uint *ids );


위 커맨드는 미사용 쿼리 개체 이름 n개를 ids에 넣어 반환한다. 이 이름들은 사용됨으로 마크되지만 BeginQuery, BeginQueryIndexed, QueryCounter에 처음 쓰이기 전에는 어떤 개체도 이 이름들에 연관되지 않는다. (4.3절)


void CreateQueries( enum target, sizei n, uint *ids );


위 커맨드로도 쿼리 개체를 생성할 수 있다. CreateQueries는 미사용 쿼리 개체 이름 n개를 ids에 넣어 반환하며, 각각은 target이 명시된 새 쿼리 개체를 나타낸다. target은 4.2.1절에 서술된 쿼리 개체 타겟 중 하나여야 한다. 생성된 쿼리 개체의 상태는 QUERY_RESULT_AVAILABLE = TRUE이며 QUERY_RESULT의 값은 0이다.


void DeleteQueries( sizei n, const uint *ids );


위 커맨드는 ids에 들어있는 n개 이름이 가리키는 쿼리 개체들을 삭제한다. 쿼리 개체가 삭제되면 그 이름은 미사용이 된다.


GL이 지원하는 쿼리 종류마다(TIMESTAMP 타입의 타이머 쿼리는 제외) 가능한 활성 쿼리들 각각에 대해 활성 쿼리 개체  이름을 가진다. 활성 쿼리 개체 이름이 0이 아니면 GL이 해당하는 정보를 현재 추적하고 있는 것이고, 쿼리 결과가 그 쿼리 개체에 기록될 것이다. 활성 쿼리 개체 이름이 0이면 그런 정보는 추적되지 않는 중이다.


void BeginQueryIndexed( enum target, uint index, uint id );


위 커맨드로도 쿼리 개체를 생성하고 활성화할 수 있다. target은 수행할 쿼리의 타입을 나타낸다. target으로 유효한 값들은 뒤에서 자세히 논의한다.


void BeginQuery( enum target, uint id );

BeginQueryIndexed(target, 0, id);


위의 두 커맨드는 동등하다.


void EndQueryIndexed( enum target, uint index );


위 커맨드는 target과 index에 의해 기술되는 활성 쿼리가 추적할 일련의 커맨드의 끝을 지정한다. target과 index의 의미는 BeginQueryIndexed에서와 같다.


void EndQuery( enum target );

EndQueryIndexed(target, 0);


위의 두 커맨드는 동등하다.


GL 커맨드 세트를 완전히 수행하는 데 걸린 시간(time elapsed query)이나 GL의 현재 시간(timer query)을 쿼리 개체를 이용하여 추적할 수 있다. (4.3절)


target을 TIME_ELAPSED로 하고 BeginQuery와 EndQuery를 호출하면 GL은 시간 경과 쿼리에 사용되는 타이머를 시작하고 중지할 준비를 한다. 타이머의 시작과 중지는 GL 클라이언트 스테이트, 서버 스테이트, 프레임버퍼에 대한 이전의 모든 커맨드의 영향이 완전히 끝난 후 이뤄진다. BeginQuery와 EndQuery 커맨드는 타이머가 실제로 시작 또는 중지되기 전에 반환될 수 있다. 시간 경과 쿼리가 완전히 중지되면 나노초 단위의 경과 시간이 연관된 쿼리 개체의 쿼리 결과값으로 기록되고, 그 개체의 쿼리 결과는 접근 가능으로 마크된다.


void QueryCounter( uint id, enum target );


위 커맨드는 타이머 쿼리 개체를 생성한다. target은 TIMESTAMP여야 한다. target을 TIMESTAMP로 하고 CreateQueries를 호출해도 TIMESTAMP 쿼리 개체를 생성할 수 있다. QueryCounter를 호출하면 GL은 현재 시각을 연관된 쿼리 개체에 기록한다. GL 클라이언트 스테이트, 서버 스테이트, 프레임버퍼에 대한 이전의 모든 커맨드가 완전히 완료된 후에 시각이 기록된다. 타이머 쿼리는 target이 TIME_ELAPSED인 BeginQuery/EndQuery 블록 내에서 사용할 수 있고, 그 쿼리 개체의 결과에 영향을 주지 않는다.


GL의 현재 시각은 기호 상수 TIMESTAMP로 GetIntegerv 또는 GetInteger64v를 호출하여 쿼리할 수 있다. 이전의 모든 커맨드가 GL 서버에 도달한 후의 시각이 반환되지만, 그 커맨드들이 반드시 실행되었다고는 할 수 없다. 동기 커맨드와 비동기 타임스탬프 쿼리 개체 타겟을 조합하면, GL 서버에 커맨드가 도달한 시각과 프레임버퍼에 실현되는 시각 사이의 레이턴시를 애플리케이션에서 측정할 수 있다.




5장

공유 개체와 다중 컨텍스트

이 장에서는 여러 OpenGL 컨텍스트가 공유하는 개체를 고려하여, 삭제 동작이나 공유 개체의 변경이 컨텍스트 간에 전파되는 방식을 다룬다.


컨텍스트 간에 공유되는 개체로는 버퍼 개체, 프로그램 개체, 셰이더 개체, 렌더버퍼 개체, 샘플러 개체, 싱크 개체, 텍스처 개체 등이 있다. (이름 0인 텍스처 개체는 제외)


이들 개체 중 일부는 다른 개체의 데이터 스토어의 일부 또는 전체의 (또다른 해석인) 뷰(view)를 포함한다. 그 예로 버퍼 개체의 데이터 스토어에 대한 뷰를 포함하는 텍스처 버퍼 개체, 다른 텍스처 개체의 데이터 스토어에 대한 뷰를 포함하는 텍스처 뷰가 있다. 뷰는 데이터 스토어가 관찰되는 개체에 대한 참조로서 작동한다.


다른 개체들을 참조하는 개체로는 프레임버퍼, 프로그램 파이프라인, 쿼리, 트랜스폼 피드백, 버텍스 어레이 개체가 있다. 이런 개체들은 컨테이너 개체라고 하며 공유되지 않는다.


구현에 따라 서로 다른 OpenGL 버전 또는 한 OpenGL 버전의 서로 다른 프로필들을 구현하는 컨텍스트 간의 공유를 허용하기도 한다. (부록 E)


--- 작업 중 ---



부록 C

OpenGL SPIR-V 실행 환경

C.1 요구되는 버전과 포맷

구현체들은 SPIR-V의 1.0 버전과 OpenGL Shading Language를 위한 SPIR-V 확장 인스트럭션의 1.0 버전을 지원해야 한다. (1.3.4절)


ShaderBinary에 전달된 SPIR-V 모듈은 호스트의 엔디안에 따라 일련의 32비트 워드로 해석되며, 리터럴 문자열들은 SPIR-V 명세서 2.2절에 서술된 대로 패킹된다. SPIR-V 모듈의 처음 몇 개 워드는 SPIR-V 명세서 2.3절에 서술된 대로 매직 넘버와 SPIR-V 버전 넘버여야 한다.

C.2 유효 SPIR-V 내장 변수 데코레이션

구현체들은 표 C.1에 서술된 내장 변수 데코레이션들을 지원해야 한다.

C.3 유효 SPIR-V 기능

구현체들은 표 C.2에 서술된 OpCapability에 의해 선언되는 capability operand들을 지원해야 한다.

C.4 검증 규칙

  • 모든 진입점(entry point)은 반환값이 없고 인자를 받지 않아야 한다.
  • Logical 어드레싱 모델을 써야만 한다.
  • 실행을 위한 Scope는 다음으로 한정한다.
    • Workgroup
    • Subgroup
  • 메모리를 위한 Scope는 다음으로 한정한다.
    • Device
    • Workgroup
    • Invocation
  • 이미지
    • OpTypeImage는 Sampled Type에 대해 스칼라 32 비트 float 또는 32 비트 정수 타입을 선언해야 한다.
    • OpSampledImage는 Image 피연산자만을 소비해야 한다. 이 피연산자의 타입은 Sampled 피연산자가 1이여야 한다.
    • OpTypeImage의 Depth 피연산자는 무시된다.
  • AtomicCounter 스토리지 클래스
    • 따로 명시하지 않는 한 AtomicCounter 스토리지 클래스에 선언된 변수들은 부호 없는 32 비트 정수여야 한다.
    • 아토믹 인스트럭션을 사용할 때 Memory Semantics 피연산자는 AtomicCounterMemory여야 하며, 메모리 순서 지정 비트를 포함하지 않아야 한다. (Relaxed 시맨틱을 함의)
  • 데코레이션
    • Flat, NoPerspective, Sample, Centroid 데코레이션은 스토리지 크래스가 Input이 아닌 변수나 프래그먼트 셰이더 엔트리 포인트가 아닌 인터페이스 내에서 사용된 변수에 쓰여서는 안 된다.
    • Patch 데코레이션은 버텍스, 지오메트리, 프래그먼트 셰이더 스테이지의 진입점의 인터페이스 내의 변수에 쓰여선 안 된다.
    • OpTypeRuntimeArray는 Uniform 스토리지 클래스 안의 OpTypeStruct의 마지막 멤버에만 쓰여야 하며, BufferBlock으로서 데코레이션되어야 한다.
    • ... 등등

C.5 SPIR-V 인스트럭션의 정확도와 동작

다음 규칙들은 단정밀도, 배정밀도 부동소수점 인스트럭션에 적용된다.
-> 원문 참조

C.6 GLSL.std.450 인스트럭션의 정밀도

표 C.4의 인스트럭션들을 통해 특별히 정의된 GLSL.std.450 확장 인스트럭션은 표에 서술된 정확도를 따른다. 여기에 나열되지 않았거나, 표의 인스트럭션들을 통해 정의되지 않은 GLSL.std.450 확장 인스트럭션은 정밀도가 정의되지 않는다. 삼각함수와 행렬식이 그런 경우다.



부록 I

버전 4.5

2014년 8월 11일 공개된 OpenGL 버전 4.5은 오리지널 버전인 1.0 이후 7번째 개정이다. OpenGL 4.5 명세서는 코어 프로필(core profile)과 호환성 프로필(compatibility profile)이 존재한다. 본 문서는 코어 프로필을 다룬다. OpenGL 4.5 구현은 반드시 코어 프로필을 지원하는 컨텍스트를 생성할 수 있어야 하며, 추가로 호환성 프로필을 지원하는 컨텍스트를 생성할 수도 있다.


다음은 OpenGL 4.5에서 바뀌거나 추가된 것들을 요약한 것이다. OpenGL 4.2 이전의 변경점은 본 명세서에서 생략되었으며 OpenGL 3.0 명세서와 4.2 명세서에서 찾을 수 있다. 이 명세서들은 OpenGL Registry에서 볼 수 있다.


새로 추가된 피처

  • GL_ARB_clip_control
  • GL_ARB_cull_distance
  • GL_ARB_ES3_1_compatibility
  • GL_ARB_conditional_render_inverted
  • GL_KHR_context_flush_control
  • GL_ARB_derivative_control (OpenGL Shading Language 전용)
  • GL_ARB_direct_state_access
  • GL_ARB_get_texture_sub_image
  • GL_KHR_robustness
  • GL_ARB_shader_texture_image_samples (OpenGL Shading Language 전용)
  • GL_ARB_texture_barrier
폐기된 것은 없으며 이전에 폐기된 피처 중 다시 도입된 것은 없다.

OpenGL 4.4에서 폐기된 것들은 그대로 폐기 상태이지만, 제거되지는 않았다.


부록 J

버전 4.6

2017년 7월 31일 공개된 OpenGL 버전 4.6은 오리지널 버전인 1.0 이후 8번째 개정이다. OpenGL 4.6 명세서는 코어 프로필(core profile)과 호환성 프로필(compatibility profile)이 존재한다. 본 문서는 코어 프로필을 다룬다. OpenGL 4.6 구현은 반드시 코어 프로필을 지원하는 컨텍스트를 생성할 수 있어야 하며, 추가로 호환성 프로필을 지원하는 컨텍스트를 생성할 수도 있다.


새로 추가된 피처

  • GL_ARB_indirect_parameters
  • GL_ARB_pipeline_statistics_query
  • GL_ARB_polygon_offset_clamp
  • GL_KHR_no_error
  • GL_ARB_shader_atomic_counter_ops (OpenGL Shading Language 전용)
  • GL_ARB_shader_draw_parameters
  • GL_ARB_shader_group_vote (OpenGL Shading Language 전용)
  • GL_ARB_gl_spirv
  • GL_ARB_spirv_extensions
  • GL_ARB_texture_filter_anisotropic
  • GL_ARB_transform_feedback_overflow_query
폐기된 것은 없으며 이전에 폐기된 피처 중 다시 도입된 것은 없다.

OpenGL 4.5에서 폐기된 것들은 그대로 폐기 상태이지만, 제거되지는 않았다.


부록 K

OpenGL Registry, 헤더 파일, ARB 확장

OpenGL API에 대한 많은 확장이 벤더, 벤더 그룹, OpenGL ARB에 의해 정의되어 있다. OpenGL 명세서의 가독성을 위해 그런 확장들은 코어 언어에 통합되지 않는다. 대신 OpenGL Registry(http://www.opengl.org/registry/)에서 온라인으로 접근 가능하며, GLX나 WGL 같은 윈도우 시스템 바인딩 API에 대한 확장과 OpenGL, GLX, 관련 API의 명세서가 포함된다.


역사적으로 OpenGL을 호출하는 C와 C++ 소스 코드는 단일 헤더 파일인 <GL/gl.h>를 #include했다. 코어 OpenGL API에 더해 구현이 제공하는 모든 확장에 대한 API도 이 헤더에 정의되어 있다.


마이크로소프트 윈도우즈와 리눅스처럼 플랫폼에서 OpenGL SDK(라이브러리와 헤더 파일)가 OpenGL 드라이버와 같은 소스에서 얻어진 것이 아닌 경우가 흔해지면서, <GL/gl.h>는 드라이버가 지원하는 새 코어 API 버전과 확장을 따라갈 수가 없었다. OpenGL ARB는 새 헤더인 <GL/glext.h>를 정의하여 OpenGL Registry에서 직접 얻을 수 있도록 하였다. <GL/gl.h>와 <GL/glext.h>를 조합하면 항상 최신 OpenGL 버전의 모든 프로필에 대한 API 전체와 Registry에 정의된 모든 확장을 정의한다.


<GL/glcorearb.h>는 OpenGL 코어 프로필의 API와 코어 프로필에 호환되는 ARB 확장을 정의한다. 호환성 프로필 전용이거나 다른 확장을 위한 API는 포함하지 않는다.


<GL/glcorearb.h>와 함께 벤더 확장을 사용할 수 있는 메커니즘은 현재 Khronos가 지원하지 않는다. 수요가 없고 어떤 벤더 확장이 코어 프로필과 호환되는지에 대한 지식이 부족하기 때문이다. 미래에는 <GL/glcoreext.h> 같은 헤더가 생겨서, 코어 프로필과 호환되지만 <GL/glcorearb.h>에 정의되지 않은 EXT와 벤더 확장을 정의할 지도 모른다. 대부분의 예전 확장들은 코어 프로필과 호환되지 않는다.


호환성 프로필을 사용하는 애플리케이션은 기존의 <GL/gl.h>와 <GL/glext.h> 헤더를 #include해야 한다. 코어 프로필을 사용하고 벤더 확장이 필요하지 않은 애플리케이션은 대신 <GL/glcorearb.h> 헤더를 #include해도 된다.


구식 <GL/gl.h>와 <GL/glext.h> 대신 <GL/glcorearb.h>을 사용하면 새로 개발하는 애플리케이션에서 실수로 코어 프로필에서 제거된 구식 피처나 덜 이식 친화적인 EXT 또는 벤더 확장을 사용하는 일을 방지할 수 있다.


개발자들은 항상 Registry에서 <GL/glcorearb.h>를 다운로드하여 플랫폼 SDK가 제공하는 예전 헤더를 대체할 수 있다.


Khronos OpenGL Architectural Review Board Working Group (ARB)가 승인했거나, ARB와 Khronos OpenGL ES Working Group (KHR)가 동시에 승인한 OpenGL 확장들이 있다. OpenGL 구현이 ARB 확장과 KHR 확장을 반드시 지원할 필요는 없지만, 이 확장들은 폭넓게 이용 가능할 것으로 기대되는 것들이다. 이 확장들은 명세서의 이후 버전에서는 필수 피처에 포함될 가능성이 큰 기능들을 정의한다.


ARB 확장과 KHR 확장을 OpenGL 코어 피처, 벤더 한정적 확장과 구분하기 위해 다음 작명 방식을 사용한다.

  • "GL_ARB_name" 또는 "GL_KHR_name" 형태의 고유 name 문자열이 각 확장과 연관된다. 구현이 확장을 지원하면 이 문자열은 22.2절에서 서술하는 대로, GetStringi가 반환하는 EXTENSIONS 문자열 중 하나다.
  • 확장이 정의하는 모든 함수의 이름은 각각 FunctionARB 또는 FunctionKHR 형태다.
  • 확장이 정의하는 모든 열거형 값의 이름은 각각 NAME_ARB 또는 NAME_KHR 형태다.
  • OpenGL 확장 외에도 GLX와 WGL API와 관련된 ARB 확장이 있다. 그런 확장들의 name 문자열은 각각 "GLX_"와 "WGL_"로 시작한다. 여기서 모든 GLX 및 WGL ARB 확장을 설명하지는 않지만, 그런 확장들은 모두 Registry에 포함되어 있다.
모든 확장 목록은 원문 참조




GLSL 4.6

  1. 소개
  2. OpenGL 셰이딩 개요
  3. 기초
  4. 변수와 타입
  5. 연산자와 표현식
  6. 구문(statement)과 구조(structure)
  7. 내장 변수
  8. 내장 함수
  9. 코어 프로필을 위한 셰이딩 언어 문법
  10. normative references


1 소개

이 문서는 OpenGL Shading Language의 버전 4.60만을 기술한다. __VERSION__은 460으로 대체해야 하며 #version이 460만 허용할 것을 요구한다. OpenGL Shading Language나 OpenGL ES Shading Language의 예전 버전은 여기서 기술하는 버전의 엄밀한 하위집합이 아니며, 특히 정밀도, 이름 은닉 규칙, 인터페이스 변수 취급 면에서 그러하다. 특정 버전에 한정된 세부사항은 그 언어 버전의 명세서를 볼 것.


OpenGL API는 SPIR-V 셰이더를 조작하는 OpenGL 커맨드를 기술한다. 별개의 오프라인 툴 체인이 GLSL을 SPIR-V 중간 언어로 컴파일할 것이다. SPIR-V 생성은 #extension, #version, 프로필 같은 것으로 되는 것이 아니다. SPIR-V에 GLSL을 쓰는 것은 오프라인 툴 체인 사용에 의해 결정된다. OpenGL을 위해 SPIR-V 생성을 요청하는 방법은 그런 도구들의 문서를 볼 것.


GLSL → SPIR-V 컴파일러는 런타임에 어떤 SPIR-V 기능(capability)이 적법한지 가려내어 이 기능 외의 GLSL 피처에 대해서는 오류를 발생시켜야 한다. 이는 구현에 의존적인 한계에 대해서도 마찬가지다.


GLSL 버전 4.50 리비전 7으로부터 변경점

* Private Bug나 Private Issue에서 Private이 '사소한'인지 '비공개'인지 모르겠다. 확인 필요

  • GL_ARB_shader_atomic_counter_ops 확장이 통합되었다.
  • GL_ARB_shader_draw_parameters 확장이 통합되었다.
  • GL_ARB_shader_group_vote 확장이 통합되었다.
  • GL_ARB_gl_spirv 확장이 통합되었다.
  • 버그 16070: 전역 스코프에서 여분의 세미콜론을 허용한다.
  • GLSL 이슈 5: 몇몇 오류에서 "fail to link"가 실제로는 "a compile-time or link-time error"인 것을 명확히 함.
  • GLSL 이슈 7: gl_MaxComputeUniformComponents를 1024로 변경.
  • OpenGL API 이슈 35: SPIR-V의 transparent individual uniform 변수에 location 요구.
  • GLSL 이슈 8: interpolateAt() 피연산자가 구조체 멤버일 수 있음을 명확히 함.
  • GLSL 이슈 9: xfb_buffer가 블록 배열과 어떻게 상호작용하는지 기술. 캡쳐링 버퍼는 블록 배열 요소 별로 증가.

2 OpenGL 셰이딩 개요

OpenGL Shading Language는 여러 언어가 긴밀히 연관된 것이다. 이 언어들을 사용하여 OpenGL 프로세싱 파이프라인에 포함된 각각의 프로그래밍 가능 프로세서를 위한 셰이더들을 작성한다. 그런 프로세서로는 버텍스(vertex), 테셀레이션 제어(tessellation control), 테셀레이션 평가(tessellation evaluation), 기하(geometry), 프래그먼트(fragment), 컴퓨트(compute) 프로세서가 있다.


셰이더에서는 대부분의 OpenGL 스테이트가 추적 또는 접근 가능하지 않다. 보통은 OpenGL 파이프라인의 스테이지들 사이의 통신을 위해 사용자 정의 변수를 이용한다. 하지만 몇 가지 스테이트는 여전히 추적되며 셰이더에서 자동으로 접근 가능하다. OpenGL 파이프라인의 스테이지들 사이의 통신을 위한 내장 변수도 몇 개 존재한다.


버텍스 프로세서는 입력되는 버텍스들과 이에 연관된 데이터에 대해 작동하는 프로그래밍 가능 단위다. OpenGL Shading Language로 작성되어 이 프로세서에서 실행되는 컴파일 단위를 버텍스 셰이더라 부른다. 버텍스 셰이더들의 집합을 성공적으로 컴파일하고 링크하면 버텍스 프로세서에서 실행 가능한 vertex shader executable이 된다.


테셀레이션 제어 프로세서는 들어오는 정점들의 패치(patch)에 대해 작동하여 새 패치를 출력한다. 테셀레이션 제어 셰이더는 출력 패치의 각 정점에 대해 호출된다. 각 호출마다 입력 또는 출력 패치들의 어느 속성도 읽을 수 있지만 대응하는 출력 패치 정점의 속성들만 쓰기 가능하다. 테셀레이션 제어 셰이더 호출들은 실행 순서가 정의되지 않고 독립적으로 실행되지만 내장 함수 barrier()를 이용해 실행 순서를 동기화할 수 있다.


테셀레이션 평가 프로세서는 테셀레이션 프리미티브 제너레이터가 생성한 정점의 위치 및 기타 속성들을 입력 정점들의 패치를 이용해 평가한다. 테셀레이션 평가 셰이더 호출마다 입력 패치의 모든 정점 및 프리미티브 내에서 정점의 상대 위치를 나타내는 테셀레이션 좌표를 읽을 수 있다.


기하 프로세서는 어쩌고 저쩌고


프래그먼트 프로세서는 어쩌고 저쩌고


컴퓨트 프로세서는 머라머라



3 기초

OpenGL Shading Language에서 쓰는 문자 집합은 UTF-8 인코딩된 유니코드다. 전처리 후 GLSL 토큰 스트림에는 다음 문자들만이 허용된다.

원문 참조


line-continuation 문자(\)로 여러 줄을 연결할 수 있다. 공백 문자들은 제거되지 않는다.


float f\

oo;

// "float foo;"와 동일. 단 \와 oo 사이에 newline 외에 아무 것도 없어야 한다.


전처리기 지시문들: 3.3절


# 앞에는 공백과 탭만 가능하다. 지시문은 newline으로 끝난다.


구현체는 매크로 이름을 최소한 1024 문자까지 지원해야 한다.


__LINE__ 매크로는 (지금까지의 newline 개수 + 1)로 치환된다.

__FILE__ 매크로는 현재 처리되는 source string number로 치환된다.

__VERSION__ 매크로는 OpenGL shading language의 버전 넘버로 치환된다. 이 문서에서 서술하는 버전에 따르면 460으로 치환된다.


관례에 따라 __로 시작하는 모든 매크로 이름은 소프트웨어 레이어에서 사용하도록 예악되어 있다. 그런 이름을 셰이더에서 정의하거나 정의를 제거하는 것 자체는 에러가 아니지만 의도치 않은 결과를 야기할 수 있다. GL_으로 시작하는 모든 매크로 이름도 예약되어 있으며 그런 이름을 정의 또는 제거하려 하면 컴파일 오류가 발생한다.



Comments