2013-03-30 2 views
5

3D 응용 프로그램이 실행되는 동안 텍스처를 비동기 적으로로드하는 방법은 무엇입니까? OpenGL 컨텍스트는 스레드로부터 안전하지 않으며 다른 스레드에서 분리해야한다는 것을 이해합니다.비동기 텍스처로드 기능

그러나 내 주요 문제는 실제로 Windows 및 C++에서이를 구현하기위한 적절한 다중 스레드 기능/프레임 워크를 선택하는 것입니다. 표준 lbrary에서 스레딩 지원을 포함하여 C++ 11에 대해 많이 들었습니다. 기본 단계?

가장 안전한 방법은 무엇입니까? 그리고 다른 스레드에서 수행 된 변경 사항을 등록하는 다른 컨텍스트의 상태를 어떻게 업데이트합니까? glFlushglBind*이 의심 스럽습니까?

+0

실제로 OpenGL 및 OpenGL 컨텍스트 **는 ** 스레드로부터 안전합니다. 한 번에 두 개 이상의 스레드에서 단일 컨텍스트를 활성화 할 수 있습니다. – datenwolf

답변

5

텍스처를로드하는 데 가장 시간이 많이 걸리는 부분은 일반적으로 디스크 액세스 및 형식 변환입니다. 둘 다 OpenGL과 독립적이므로 다른 스레드에서 안전하게 수행 할 수 있습니다. 일단 텍스쳐가 메모리로 그리고 원하는 포맷으로 읽혀지면 OpenGL 버퍼로의 실제 복사는 상당히 빠릅니다.

스레드 프로그래밍에 대한 자세한 내용은이 대답에는 너무 복잡하지만 주위에 좋은 설명서가 있고 머리에 클릭하면 꽤 쉽게 (포인터와 메모리처럼).

여기의 일반적인 개념은 텍스처 홀더 객체 목록 (파일/이름, 초기 null 버퍼 및로드 완료 플래그 포함)을 작성하고로드 할 스레드가 생성 될 때이를 전달하는 것입니다 . 로딩 스레드는 목록을 관통하고 각 파일을 열고 메모리에로드 한 다음 버퍼를 목록 항목에 첨부 한 다음로드 된 플래그를 설정하고 카운터를 증가시킵니다. 메인 스레드는 새로로드 된 텍스처를 가져 와서 OpenGL 텍스처로 복사하고 진행률 막대 또는 로딩 표시기가 무엇이든간에 증가시킵니다. 목록의 모든 텍스처에 버퍼가 있고로드 된 것으로 플래그가 지정되면 다른 스레드의 작업이 완료되고 중지 될 수 있습니다 (또는 미래의 텍스처를로드하기 위해 남아 있습니다).

해당 모델의 주요 장점은 실제 그래픽 컨텍스트를 공유 할 필요가 없기 때문입니다. thread-safe (DirectX) 할 수있는 API에서는 성능상의 불이익이 있으며, OpenGL은 다중 컨텍스트를 갖거나 제대로 공유 할 수 있도록 적절한 작업이 필요합니다. 텍스처를로드 할 때 무거움은 일반적으로 파일 읽기 및 매개 변수 검사입니다. 형식 변환 또는 회전을 수행하지 않으면 디스크 액세스가 너무 작아 질 수 있습니다. 비디오 메모리에 대한 실제 사본은 고도로 최적화되어있어 병목 현상이 발생하지는 않습니다 (GPU 호출 비용을 인식 할 수있는 도구로 프로파일 링을 시도해보십시오). 이 작업은 OpenGL에 직접 의존하지 않으므로 걱정하지 않아도 다른 스레드로 푸시 할 수 있습니다.

특별히 Windows를 사용하는 경우 간단한 콜백 모델 (함수 및 초기 매개 변수 제공,이 경우 텍스처 목록 제공)을 사용하여 API를 사용할 수있는 내장 스레딩 함수가 있습니다 요구). 개인적으로 C++ 11 스레딩 지원에 익숙하지 않거나 Visual Studio에서 어떻게 작동하는지에 대해서는 잘 모르겠다.

+0

좋은 답변입니다. 예, C++ 11의'std :: thread'는 MSVC++에서 작동합니다. 사용법은'boost :: thread'와 매우 비슷합니다. –

0

@ssube의 대답은 작업의 복잡성에 대한 정확한 설명이지만 "OpenGL은 여러 컨텍스트가 있거나 제대로 공유하고 있는지 확인하기 위해 적절한 부분의 작업이 필요합니다."라고 가정합니다. 동의하지 않는다.

쉬운 용액으로, 예를 들면, 프로그램의 시작에서, (도면의) 메인 문맥 (텍스처 로딩) ​​보조 콘텍스트를 생성하는 것이다

m_hRCDrawing = wglCreateContext(m_hDC); 
m_hRCSecondary = wglCreateContext(m_hDC); 

다음 데이터를 공유 당신이 "텍스처로드"에서 더 GL 컨텍스트가 없습니다 스레드를 텍스처를 읽을하려고 할 때

wglShareLists(m_hRCSecondary, m_hRCDrawing); 

마지막으로, 당신은 단순히 호출 할 수 있습니다 : 다음 m_hRCSecondarym_hRCDrawing 상황 사이에 수행 할 수 있습니다

wglMakeCurrent(m_hDC, m_hRCSecondary); 

이 스레드 내에로드 된 모든 애셋은 그리기 스레드의 컨텍스트에서 공유됩니다.

약간 더 철저한 설명은 here입니다.