지형 덩어리의 메쉬를 보유하는 정점 버퍼가 있습니다. 플레이어가 지형을 편집 할 때마다 해당 청크의 메쉬가 재생성되어 버텍스 버퍼에 업로드되어야합니다. 메쉬 재생성에는 시간이 걸리기 때문에 비동기 작업자 스레드에서 처리합니다.다중 스레드 OpenGL 버퍼 액세스를 동기화하는 방법은 무엇입니까?
작업 스레드가 새 데이터를 업로드하는 동일한 순간에 주 스레드가 버퍼를 그립니다. 즉, 플레이어가 지형을 편집 한 후에 손상된 청크가 한 프레임 렌더링됩니다. 그것은 단지 한 번 그리고 그 후에, 올바른 버퍼가 그려지기 시작합니다.
이런 종류의 의미가 있어도 같은 시간에 동일한 데이터를 쓰고 읽지 않아야합니다. 따라서 이전 버퍼를 업데이트하는 대신 새 버퍼를 작성하고 버퍼를 채우고 바꿨습니다. 스와핑은 지형 청크 구조체 내에 저장된 버퍼 ID를 변경하는 것이므로 원자가되어야합니다. 그러나, 그것은 도움이되지 못했습니다.
OpenGL 명령이 GPU의 큐로 보내지기 때문에 CPU의 응용 프로그램이 계속 실행될 때 실행될 필요가 없습니다. 그래서 새로운 버퍼가 실제로 준비되기 전에 버퍼를 교체했을 것입니다.
또한 버퍼 액세스에 뮤텍스를 사용하여 버퍼를 전환하는 방법을 시도했습니다. 메인 쓰레드는 드로잉하는 동안 뮤텍스를 잠그고 작업자 쓰레드는 새로운 버퍼 데이터를 업로드하는 동안 그것을 잠급니다. 그러나 이것 역시 도움이되지 않았고 OpenGL의 비동기 성질 때문일 수도 있습니다. 메인 스레드는 실제로 그리지 않았지만 그리기 명령을 GPU에 보냅니다. 반면에 실제로 명령 대기열이 하나뿐일 때 버퍼를 업로드하고 그리는 것은 결코 동시에 발생하지 않을 수 있습니까?
정의되지 않은 버퍼가 하나의 프레임에 그려지는 것을 방지하기 위해 두 스레드의 버텍스 버퍼 액세스를 어떻게 동기화 할 수 있습니까?
내가 귀하의 상황을 정확하게 이해한다면, 나는 말할 필요가 있습니다. 그것은 그렇게 작동하지 않아야합니다. 버퍼 업데이트는 그들과 함축적 인 동기화를 수행하며,'glBufferSubData (...) '같은 각각의 호출은 효과적으로 원자 적이다. 구현이 올바르게 준수하고 있다면 다른 스레드에서 나타나는 부분적인 쓰기에 대해 걱정할 필요가 없습니다. 즉, 처음부터 이런 방식으로 작업하려고하는 오버 헤드가 있습니다. 렌더링 스레드가 다른 스레드 (예 : 정면)에서 읽는 동안 작업자 스레드가 쓰는 순환 버퍼 (예 : 백 버퍼)를 고려 했습니까? ? –
그런데 버퍼를 업데이트하는 데 API의 어떤 부분을 사용하고 있습니까? 버퍼를 매핑하고 매핑 해제하거나'glBufferSubData (...) '를 사용하고 있습니까? –
@ AndonM.Coleman : 흠. 방금 daijar가 다중 컨텍스트를 사용하고 있다고 가정합니다. 그렇지 않으면 질문이 실제로 의미가 없습니다. – derhass