2013-08-18 5 views
4

그래서 외부 소스에서 (잠재적으로 색상 및/또는 표준) 점 스트림을 수신하는 시스템 (OpenGL 4.x 사용)이 있습니다. 그리고이 점들을 GL_POINTS로 그려야합니다. 색상을 지정할 수있는 전환 가능한 셰이더를 실행해야합니다 (색상은 절차 적으로 생성 될 수도 있고, 정점 색상 또는 법선 방향에서 생성 될 수도 있음).스트리밍 지점을 업로드하고 가끔씩 제거하는 가장 빠른 방법

스트림은 일정한 간격 (4에서 10hz)으로 임의의 수 (일반적으로 1k에서 70k까지의 지점)의 지점 그룹 (정상 또는 색상 없음 또는 없음)을 수신하는 것으로 구성됩니다. 현재 점을 가리키고 지금까지받은 점을 모두 그립니다.

내 꼭지점 유형이 변경되지 않는다는 것을 보증합니다. 예상되는 스트리밍 시작 부분에서 말 했으므로 pos + normal + color, pos + normal, pos +와 함께 인터리브 된 정점을 사용하고 있습니다. 색상, 또는 그냥 pos.

내 현재 해결 방법은 최대 버텍스 카운트 (다이나믹 힌트로 할당 됨)로 지정된 구성 파일에 적절한 버텍스 유형의 인터리브 된 버텍스 VBO (주변 VAO와 함께)를 할당하는 것입니다.

새로운 점으로 glBufferSubData를 통해 현재 채워지지 않은 VBO를 채 웁니다. 현재 프론티어 VBO가 얼마나 많은 버텍스를 가지고 있는지 계산 (activePoints)하고 glBufferSubData를 사용하여 activePoints로 시작하는 범위를 채 웁니다. 현재 업데이트 그룹에 내 프론티어 버퍼에 들어갈 수있는 것보다 많은 정점이있는 경우 (이후 VBO 당 버텍스 수를 제한), 새로운 VBO를 할당하고 범위가 0에서 시작하여 마지막 업데이트에 추가되지 않은 포인트 수로 끝납니다. 이 일을 계속 반복하십시오. 업데이트 그룹이 2 개 이상의 버퍼를 넘는 경우는 거의 없습니다.

것은 내가 glDrawArrays와 numVertices 맥스 버퍼 허용 크기 같다 glDrawArrays (m_DrawMode, 0, numVertices), 내 프론티어 완충액 내 VBOs (-1) 렌더링 렌더링 할 때 (m_DrawMode, startElem을 numElems) 유효한 꼭지점으로 완전히 채워지지 않았 음을 설명합니다.

물론 어떤 시점에서 대화식으로 그릴 수있는 것보다 많은 점수를 가질 것이므로 필요에 따라 가장 오래된 (LRU alg에 따라) 할당을 해제하는 LRU 메커니즘이 있습니다.

더 좋은 방법이 있습니까? 버퍼 고아? 스트리밍 힌트 요? 지도 대 SubData? 다른 것?

두 번째 문제는 한 번에 10 개에서 2000 개 사이 인 점을 (불규칙한 간격으로) 제거하도록 요청되었습니다. 그러나이 점들은 처음에받은 순서대로 불규칙적으로 배치되어 있습니다. 어떤 버퍼가 현재 어느 버퍼에서 벗어나지는 않지만 어떤 범위보다 더 많은 버퍼가 있는지 알 수 있습니다. 나는 오른쪽 버퍼로 오프셋을 찾고 glBufferSubData를 1 (범위가 희박한 버퍼가 있음)로 호출하여 하나씩 오프셋을 제거하고 위치를 멀리 떨어진 위치로 변경하여 "제거"했습니다. 그들은 결코 보이지 않을 것이다. 결국 버퍼를 삭제 요청에서 삭제해야한다고 추측하지만, 현재 그렇게하지는 않습니다.

어떻게 처리할까요?

+0

사용하지 않는 정점을 물리적으로 제로 (zero)로 만드는 대신에, glDrawElements (...)를 사용하는 것이 좋습니다. 그런 다음 실제로 데이터가있는 모든 점의 배열을 전달합니다. 사용하지 않거나 자유로운 버텍스를 내부적으로 보관할 수 있지만, 자유 버텍스를 제로 아웃하는 버스 대역폭을 낭비하는 것은 분명합니다. 그들이 그대로있는 것처럼 그들을 남겨주세요. 그러나 정답은 렌더링되지 않아야합니다/정크가 포함되어 있음을 인정하십시오. –

+0

그래서 삭제를 만들고 인덱스 (또는 IBO)로 채워진 새 VBO를 만들 것을 제안합니다. 매번 4 포인트를 말합니다. 버퍼에서 300k를 제거해야합니까? 그런 다음 glDrawArrays와 함께 glDrawElements를 그립니다. – Ryan

+0

아닙니다. 나는 정점 버퍼에 같은 크기의 IBO를 할당 할 것을 제안했다. 처음에는 0-n (n은 VBO 크기)의 값으로 순차적으로 채워질 것이다. 임의의 위치 또는 일련의 연속 된 정점에서 하나의 정점을 제거하려면'glBufferSubData (...) '를 사용하고 IndexArray [n]의 값을 유효한 정점을 가리키는 인덱스로 바꿉니다. 이렇게하면 정점 위치를 다시 정의하거나 렌더링시 제거 된 정점을 "숨기"위해 32 비트 w 좌표를 추가하는 대신 16 비트 인덱스를 다시 정의하는 것만으로도 해결할 수 있습니다. –

답변

4

특히 "삭제"해야 할 때 매핑이 glBufferSubData보다 효율적일 수 있습니다. 명시 적 플러시는 특별한 도움이 될 수 있습니다. 또한 매핑을 사용하면 버퍼 채우기를 다른 스레드로 오프로드 할 수 있습니다.
액세스 비트가 올바로 지정되었는지 (또는 성능이 최악인지) 확실하게 확인하십시오. 특히 수행중인 작업이 모두 쓰기 인 경우 "읽기"영역을 매핑하지 마십시오.

아마도 정점 버퍼에서 포인트를 삭제하는 것은 쉽지 않습니다. '소수점'(예 :10 또는 20) 나는 단지 w = 0을 설정하여 무한대로 이동시키고 이전처럼 모든 것을 계속 그릴 수 있습니다. 클립면이 무한대가 아닌 경우에는 무시합니다. 명시적인 플러시를 사용하면 별도의 복사본을 메모리에 둘 필요조차 없습니다.
"많은"점수 (예 : 1,000)의 경우 glCopyBufferSubData을 사용하여 '구멍'을 제거하는 것이 좋습니다. GPU에서의 메모리 이동 속도는 빠르며, 수천 포인트의 메모리가 문제가 될만한 가치가 있습니다. 그런 다음 모든 정점 버퍼에 대한 개수를 유지해야하므로 일부 정점 버퍼를 제거한 후에 더 적은 점을 그립니다.

전체 버텍스 버퍼를 "삭제"하려면, 버텍스 버퍼를 고아 (재사용)해야합니다. OpenGL은 그 자체로 올바른 일을 할 것이며, 메모리를 계속 그리고 재사용하는 것이 가장 효율적입니다.

이 경우 하지 도움을 것이다 안돈 M. 콜맨의 의견에 제안 일반적으로 좋은 조언을 대신 glDrawArraysglDrawElements입니다 사용하지만. 이유는 변환 후 캐시는 꼭지점을 인덱스로 태그 지정하여 작동하므로 그리기 요소는 변환 후 캐시를 활용하지만 그리기 배열은 그렇지 않습니다. 그러나 변환 후 캐시는 삼각형 목록이나 삼각형 스트립과 같은 복잡한 형상에서만 유용합니다. 드로잉 포인트이므로 어떤 경우에도 포스트 변형 캐쉬는 사용하지 않습니다. 그러나 인덱스를 사용하면 GPU와 PCIe 버스에서 메모리 대역폭이 증가합니다.

+0

"...하지만이 경우 ** ** 도움이되지 않습니다." 그래? 내 생각에 요소 배열 (VBO에 저장할 수있는)에서 16 비트 인덱스를 설정하면 32 비트 부동 소수점 구성 요소 (w)를 정점 버퍼에서 0.0으로 설정하는 것보다 비용이 적게 듭니다. (또는 최악의 경우 경우, 질문에 설명 된대로 전체 정점을 제로). 요소 배열은 모든 그리기 호출시 GPU에 x'fer되어야하므로 요소 인덱스를 더미 값 (대체로 기본 인덱스가 작동하는 방식과 비슷 함)으로 대체하는 것이 버스 오버 헤드가 적은 것처럼 보입니다 (어쨌든). . –

+0

@ AndonM.Coleman : 음, 새로운 버퍼를 업로드하는 것과 같은 "제로 아웃"포인트에 대해 서로 다른 인덱스 세트를 업로드해야합니다. PCIe 대역폭은 크지 만 대기 시간은 "매우 0이 아닌"고정 최소값을 갖습니다. 즉, 모든 종류의 전송을 수행하는 것은 힘들지 만 다소 더 많거나 적은 데이터를 업로드하더라도 영향은 거의 없습니다. 다른 한편, 인덱스를 사용하는 경우 인덱스를 업로드해야합니다 ("구멍이없는 완전한 버퍼의 경우에도). 모든 그리기 호출이 아니라 모든 변경 사항에 대해 인덱스가 GPU에서 메모리를 차지합니다. 나는 그들이 도움보다는 오히려 해를 입을 것이라고 확신합니다. – Damon

+0

그래서 내 국경 VBO에 포인트를 추가하는 경우. 그것은 이미 100k 한계 (내가 부과 한)에서 10k 포인트를 말하고이 업데이트에 60k 포인트를 추가하려고합니다. 해당 버퍼의 subData가 아닌 매핑이 가장 좋다고 말할 수 있습니다. 추가 업데이트를 위해 버퍼를 고아 (삭제 및 즉시 다시 작성)하는 것이 적절한 경우 언제 적용됩니까? – Ryan