2016-12-22 1 views
-1

전달 + 음영에 대한 전역 연결 목록을 만들려고하지만 구현 중에 어려움이있는그룹 간의 OpenGL Compute Shader 동기화

입니다.

compute shader의 각 그룹에는 공유 변수 인 로컬 인덱스 배열이 있으며이 배열의 길이는 가변입니다 (용량은 일정하지만 내용은 그렇지 않습니다). 다음은 그 예입니다 :

shared int array [1024]; // GLSL의 선언

공유 int 길이; // 작업 그룹의 공유 변수이기도합니다.

그룹 0 : 길이 = 4, 어레이 = 3, 5, 7, 1, -1, -1, -1, -1 ... (-1 = 유효하지 않음)

그룹 1 : 길이 = 2, 배열 = 1, 6, -1, -1, -1 ....

그룹 2 : 길이 = 1, 배열 = 8, -1, -1, -1, -1 .. ..

이제이 인덱스를 전역 인덱스 배열에 병합하고 싶습니다. 즉 셰이더 저장 버퍼 객체.

글로벌 인덱스 어레이 : 3, 5, 7, 1, 1, 6, 8, -1, -1, -1 ......

어려움 순서는 그룹 인덱스를 기반으로 다른 그룹간에 동기화하는 방법을 모르겠습니다. OpenGL의 barrier()는 동일한 그룹 내에서만 동기화를 보장하기 때문에.

다른 게시물에서 OpenGL은 다른 그룹 간의 동기화를 지원하지 않는다고합니다.

OpenGL Compute shader sync different work groups

그래서, 내 질문입니다. 어쨌든 내 목표를 달성 할 수 있습니까?

예를 들어 업데이트를 완료 한 최신 그룹 ID 및 전역 인덱스 배열의 오프셋과 같은 일부 셰이더 저장소 버퍼 개체를 선언 할 수 있습니까?

예 :이 시도가 작동 윌

unit latestGroupIDUpdated = -1; // a SSBO 
unit globalIdxOffset = 0; // a SSBO 
in each group: 
while(myGroupId - 1 != latestGroupIDUpdated) 
{ //keep waiting } 

// my previous group has updated the global list 
globalIdxOffset+= myArrayLength; 
latestGroupIDUpdated = myGroupId; 
//now start appending the local index array into global index array 

? 아니면 실패하고 왜 그럴까요?

실패 할 경우 어떤 방법을 권장합니까? 당신은 1D에서 로컬 그룹을 조직처럼의 모양으로

+0

"그룹"이라고하면 "작업 그룹"을 의미합니까? 그렇다면 작업 그룹은 다른 "길이"를 가질 수 없습니다. "길이"를 사용하면 그룹당 호출 수를 나타냅니다. –

+0

예, 그룹은 작업 그룹을 의미합니다 –

+0

그리고 다른 길이입니까? –

답변

0

, 그것은 같습니다 당신이 glDispatch(n * X, 1, 1)라고하면

layout(local_size_x = X​, local_size_y = 1, local_size_z = 1) in; 

, 당신은 N 그룹 것입니다. n 개의 그룹 사이의 프로세스도 병렬로 실행되므로 각 groupID이 업데이트되는 순서를 알 수 없습니다. 'latestGroupIDUpdated'을 사용하면 작동하지 않습니다. 여기

는 내장 변수

gl_GlobalInvocationID (gl_GlobalInvocationID.x in our case) 
gl_GlobalInvocationID.x = gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x; 

---//gl_WorkGroupID.x; [0, n) - 'n' : num groups you dispatched 

---//gl_WorkGroupSize.x; X - size (3 in your example) 

---//gl_LocalInvocationID.x; [0, gl_WorkGroupSize.x) - or [0, X) 

당신은 'length을'저장하기 'global'SSBO 목록에 인덱스 gl_GlobalInvocationID.x을 사용할 수있는 활용해야한다, 내 방법입니다.뭔가 같이 :

GlobalLengthList[gl_GlobalInvocationID.x] = length; 

이 모든 것은 단지 'global'SSBO 목록에서 그룹 순서에 따라 동적 값 'length'을 저장하는 것입니다. 이 모든 'length'은 C/C++ 응용 프로그램에서 glMemoryBarrier()을 호출하면 업데이트됩니다.

그런 다음 '길이'배열의 "접두사 합계"를 포함하도록이 배열을 수정해야합니다. 이 프로세스는 고도로 병렬 처리됩니다. 시간을 절약하려는 경우 별도의 계산 쉐이더에서이 작업을 수행 할 수 있습니다. (나는 길이 배열이 길면 이것을 보길 권한다.) CPU에서이 작업을 수행 할 수도 있습니다. 당신의 PrefixSumLengthArray의 마지막 값 -

당신이 포함 접두사 합계 길이 배열을 한 후에는 전체 '길이'값만큼 쉐이더 호출을 파견 다시 glDispatch()를 호출해야합니다 (의이 PrefixSumLengthArray를 부르 자). 그런 다음 gl_GlobalInvocationID을 사용하여 새로운 SSBO 목록에 색인을 만들어 배열을 저장하십시오. 다음과 같이합니다 :

int i = 0; // index to PrefixSumLengthArray array get the 'length' upto and including. 

int j = 0; // index [0, length) to get the localArray 

if (gl_GlobalInvocationID.x < PrefixSumLength[i]) { 
     GlobalArrayList[gl_GlobalInvocationID.x] = localArray[j]; 
     j++; 
} else { 
     j = 0; 
     i++; 
} 

다른 그룹간에 동기화됩니다.

+0

불필요한 '-1'값도 모두 제거합니다. –