2013-08-18 1 views
1

enter image description hereC++ OpenGL을 스레드 지형 충돌

목적은 무엇인가 :

내가 스레딩 비교적 새로운 해요. 나는 Quad-Tree 렌더링 된 지형을 빠르고 효율적으로 렌더링하려고 노력해 왔습니다. 현재 렌더링 된 지형의 양은 사용자가 모두 세부적인면에서 중요하게 뒤떨어집니다. 그래서 QuadTree를 사용하여 렌더링했습니다. 엔진은 또한 입력 및 물리학을 지원하므로 렌더링 스레드를 사용하기로 결정했습니다. 이로 인해 많은 문제가 발생했습니다.

문제 (님) : 내가 스레딩하지 않았을 때 엔진의 다른 시스템으로 인해 약간의 지연이있었습니다. 지체를 야기한 주된 원인은 QuadTree에서 지형의 로딩 및 삭제입니다. (이것이 최선의 방법인지 확실하지 않습니다.) 이제 렌더링이 매우 빠르게 진행되고 지연되는 것처럼 보이지 않습니다. 카메라가 여전히 서있을 때 게임은 잘 돌아갑니다. 나는 1 시간 동안 게임을 계속 두었고 어떤 충돌도 발견되지 않았다.

지형이로드되면 렌더링 코드에서 사용하는 여러 변수가 사용됩니다. 즉, 버퍼 바인딩 -

glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); 
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); 

    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); 
    glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW); 

    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); 
    glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW); 

이 변수는 다른 스레드와 동시에 액세스 할 수 있다고 생각합니다. 충돌을 일으 킵니다. 어떻게 해결하나요? 뮤텍스를 사용하여 시도했지만 작동하지 않는 것 같습니다. 이 문제를 해결하기 위해 어디에서 뮤텍스를 잠 그거나 잠금 해제합니까?

같은 오류가 발생할 수있는 또 다른 변수는 "IsLeaf"입니다.

많은 지형을로드 한 후에 또 다른 크래시 (std :: badAlloc)가 발생합니다. 비록 그것이 beeing 청소. 나는 이것이 나의 삭제 코드로 인한 것이라고 생각하지만, 나는 틀린 것을 모른다.

현재 타일을 추가하고 삭제하는 방법은 카메라의 범위를 확인하고 타일을 삭제/생성하는 것입니다. 나는 타일과 그 주위의 타일을 렌더링하고 싶습니다. 그러나 4 개의 기본 타일 중 하나에서 전환 할 때는 작동하지 않습니다. 범위를 사용하여 생성하는 것은 작은 타일보다는 큰 타일의 중심까지의 범위이기 때문에 작동하지 않습니다. 나는 또한 전체 맵을 몇 초마다 지우려고했는데, 이것도 효과가 있지만 더 많은 지체가있는 것으로 보인다. 창조와 파괴를 할 수있는 더 좋은 방법이 있습니까?

다른 해상도 사이에는 간격이 있습니다. 어쨌든 이것을 줄일 수 있습니까? 현재 나는 타일을 필요한 것보다 약간 더 크게 렌더링하지만 이는 주요 해상도 변경에 도움이되지 않습니다.

이러한 오류 중 하나를 수정하는 방법에 대해 알고 계신다면 대단히 감사하겠습니다.

코드 (여기에 업로드 할 너무 많은)

http://pastebin.com/MwXaymG0

http://pastebin.com/2tRbqtEB

답변

5

는 OpenGL 컨텍스트 만 (Windows의 wglMakeCurrent()를 통해) 한 번에 하나 개의 스레드에 바인딩 할 수 .

따라서 스레드에서 gl * 함수를 사용하면 안됩니다. 메모리에서 특정 변수에 대한 액세스를 보호하기 위해 뮤텍스를 사용하는 경우에도 호출이 실패합니다.

내가 제안하는 것은 렌더링 스레드로 gl * 호출을 이동하는 것이지만 지형로드, 절두체 계산, 다른 스레드의 클리핑 등과 같은 것들이 있습니다. 렌더링 스레드는 객체가 새 데이터를 가지고 있는지 확인한 다음 업데이트/렌더링의 일부로 적절한 GL 호출을 수행하면됩니다.

+2

그 밖에도 : 동일한 프레임 버퍼에서 작동하도록 여러 스레드에서 드로잉 명령을 보내면 실제로 속도가 느려집니다. 프레임 버퍼는 상호 배타적 인 리소스입니다. 그리고 여러 스레드가 그것에 드로잉 할 때 드라이버와 GPU는 문맥을 전환하는 데 많은 시간을 소비합니다. 그러나 더 많은 암시 적 동기화 포인트가 도입되어 파이프 라인을 비우고 처리량이 감소합니다. * 짧게 * ** 렌더링 코드를 멀티 스레드하지 마십시오! ** * GPU는 내부적으로 모든 것을 프래그먼트 레벨까지 멋지게 병렬 처리합니다. 그 점에서 수동으로 할 일은 아무것도 없습니다 * – datenwolf

+0

@datenwolf와 확실히 동의합니다. 모든 렌더링 호출은 단일 스레드에 있어야합니다. 텍스처/모델 데이터를 스레드 A의 시스템 메모리로로드 한 다음 gl 호출 등을 통해 드라이버에 실제로 전달하는 렌더링 스레드 (스레드 B) –

+1

OpenGL 스레드에서 VBO/PBO를 매핑 할 수 있습니다 (glMapBuffer) 그리고 I/O 스레드가 페이로드 데이터를 OpenGL 메모리로 직접 읽도록하여 하나의 추가 복사본을 피하십시오. – datenwolf