Quick Flow
객체 이름 준비 → 객체·저장소 생성 → 필요한 위치에 바인딩
→ 상태 설정·사용 → 참조 해제·삭제 요청 → 컨텍스트 종료객체 이름은 데이터 자체가 아니고, 바인딩은 복사가 아닙니다. glDelete* 호출과 GPU의 마지막 사용 완료도 구분합니다. 기본 범위는 GL 3.3 Core의 버퍼·텍스처·VAO·프로그램입니다.
이름과 저장소
GLuint 값은 OpenGL 객체를 식별합니다. 버퍼 이름을 만들었다고 정점 데이터 저장소까지 생기지 않습니다. glGenBuffers로 이름을 얻고 바인딩한 뒤 glBufferData로 저장소를 할당합니다. 초기 저장소 크기는 0이며, 데이터 포인터를 nullptr로 할당하면 내용은 초기화되지 않습니다.
서로 다른 객체 종류에서 같은 숫자가 나올 수 있습니다. 숫자가 같다고 버퍼와 텍스처가 같은 자원은 아닙니다. 삭제된 이름을 나중에 재사용할 수도 있으므로 오래된 정수 핸들을 유효성 증거로 삼지 않습니다.
// GL 3.3 Core, 현재 컨텍스트·로더가 준비된 초기화 구간
GLuint buffer = 0;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
const float points[] = {0.0f, 0.0f, 1.0f, 0.0f};
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 언바인딩해도 buffer의 저장소는 유지됩니다.
glDeleteBuffers(1, &buffer);
buffer = 0;상태가 저장되는 곳
| 상태 | 소유·영향 범위 | 실수의 결과 |
|---|---|---|
| 현재 프로그램 | 컨텍스트의 실행 상태 | 다른 프로그램에 uniform 갱신 |
| 정점 속성·요소 버퍼 연결 | VAO | 예상하지 않은 메시 데이터 사용 |
| 텍스처 이미지·파라미터 | 텍스처 객체 | 여러 draw에서 변경을 함께 관찰 |
| 텍스처 유닛 바인딩 | 컨텍스트 | sampler가 다른 이미지 읽음 |
| viewport·깊이·블렌드 | 컨텍스트 | 다음 패스에 상태가 누출 |
VAO에 버퍼를 연결하면 저장소를 복제하는 것이 아니라 참조합니다. 버퍼 내용을 바꾸면 같은 버퍼를 사용하는 draw의 입력도 바뀝니다. 반대로 glBindBuffer(GL_ARRAY_BUFFER, 0)만으로 이미 기록한 속성 연결이 지워지지 않습니다. VAO 레이아웃에서 각 상태를 나눠 확인합니다.
정리 책임
삭제 함수는 애플리케이션이 더 이상 이름을 사용하지 않겠다는 요청입니다. 이미 제출한 GPU 작업에 필요한 내부 자원을 드라이버가 즉시 파괴해 버리는 것은 아닙니다. 객체 종류와 컨테이너·공유 컨텍스트의 참조에 따라 실제 해제가 지연될 수 있습니다. 삭제를 스레드 간 인계나 GPU 완료 신호로 쓰지 않습니다.
프로그램은 사용 해제 후 삭제하고, 버퍼·텍스처 등은 해당 자원에 접근할 수 있는 컨텍스트가 유효할 때 정리합니다. C++ 소멸자가 창 파괴보다 늦게 실행되는 구조는 GL 호출에 필요한 환경을 잃을 수 있습니다. RAII를 사용하더라도 소멸 순서를 먼저 정해야 합니다.
버전과 직접 상태 접근
1.0의 상태 기반 호출에서도 컨텍스트는 중요하지만, 모든 현대 객체 종류가 존재했던 것은 아닙니다. 텍스처 객체는 1.1, 버퍼 객체는 1.5, VAO는 3.0에 코어로 들어왔습니다.
4.5 DSA에서는 glCreateBuffers·glNamedBufferData처럼 객체를 직접 지정해 수정할 수 있습니다. 수정할 객체를 바인딩하는 과정이 줄어도 draw 시 필요한 자원 연결과 동기화 책임은 남습니다. 3.3 예제에 DSA 함수 이름만 바꿔 넣지 않습니다.
참고 링크
4 sources