2012-03-17 3 views
1

조각 쉐이더는 두 개의 원자 카운터를 사용합니다. 첫 번째가 증가하거나 증가하지 않을 수도 있고 두 번째 증가 할 수도 있고 그렇지 않을 수도 있습니다 (둘 다 결코 증가하지 않을 수도 있음). 카운터를 수정하기 전에 카운터의 현재 값이 항상 읽혀지고 나중에 카운터가 수정되면 이전에 읽은 값이 일부 사용자 지정 논리에 사용됩니다. 이 모든 일은 (대부분 언롤 가능) 루프에서 발생합니다.조각 쉐이더에서 GLSL 원자 카운터 (및 분기)

구상 대략 이런 흐름 : 몇 가지 작은 unrollable 루프에서

  • 는 (컴파일 시간 해석을 const) 0-20위한 AC1 및 AC2
  • 에 대한
  • GET 카운터 값을 말한다 일부
  • 체크 값 :
  • 경우 X : 인덱스 AC1,
  • 다른 증분 AC1에 uimage1D_A에서 설정 텍셀 : 인덱스에 uimage1D_B에서 설정 텍셀 (imgwidth-AC2-1) 증가 AC2

질문 : 셰이더는 현재 카운터 값을 쿼리합니다. 항상 "최신"값을 얻나요? 현재 조각 및 차후 GPU 및 드라이버에 관해서 만 말하면서 조각 쉐이더의 방대한 병렬 처리를 여기서 잃어 버릴 수 있습니까? 분지로서는

(만약 X) - I는 (uniform) uint에 다른 (readonly restrict uniform) uimage1D의 텍셀을 비교한다. 그래서 하나의 피연산자는 분명히 균일 한 스칼라이지만 다른 하나는 이미지가 균일하지만 imageLoad().x입니다 -이 종류의 분기는 여전히 "완전히 병렬화"되어 있습니까? 두 지점이 각각 정확히 두 개의 거의 동일한 지침임을 알 수 있습니다. "완벽하게 최적화 된"GLSL 컴파일러를 가정 할 때, 이런 종류의 분기가 실속을 초래할 가능성이 있습니까?

답변

4

원자 카운터는 원자 적입니다. 그러나 각 원자 연산은 해당 연산에 대해서만 원자 적입니다. 당신은 모든 쉐이더가 카운터에서 고유 한 값을 얻을 수 있도록하려는 경우

그래서, 다음, 모든 쉐이더는 카운터 atomicCounterIncrement에 액세스해야합니다 (또는 Decrement을하지만, 그들은 모두 같은 하나를 사용해야합니다).

당신이 제안하는 일을하는 올바른 방법은 다음과 같습니다

  1. 체크 일부 값 :
  2. X 같은 경우 값을 저장
    1. atomicCounterIncrement(AC1)이 돌아왔다.
    2. 저장된 값을 uimage1D_A에 설정하는 텍셀로 사용하십시오. 다른
  3. : 값을 저장
    1. atomicCounterIncrement(AC2)는 리턴.
    2. 저장된 값을 사용하여 uimage1D_B에 무엇인가를 설정하는 텍셀 (imgwidth - val - 1)을 계산하십시오.

귀하의 "가져 오기 이후 증가"전략 일이 기다리고 경쟁 조건이다.이 (가)으로 잘못 되었기 때문에 "완전 병렬화"되어도 상관 없습니다. 그것이 빨라질 지 궁금해지기 전에 일해야합니다.

GPU 작업을 시도하기 전에 CPU에서 원자 및 스레딩에 익숙해지는 것이 좋습니다. 초보자가 원자 단위로 작업 할 때 흔히 범하는 실수입니다. GLSL 원자 및 이미지로드/저장을 성공적으로 사용하려면 스레딩 전문가 (또는 적어도 중간 수준) 여야합니다.

+0

해명에 대한 감사 및 경고 수 있습니다 uimage1D_A을 acessing 있습니다 제안합니다 :) – metaleap

1
니콜 올가미가 제안한 것처럼 당신은 당신이 이제까지 다른 커널 읽을 수 없습니다 원자 카운터에서 읽은 값을 확인하려는 경우, 당신은 반환 값, 다른 커널의 뜻을 원자 증가를 수행하고 사용할 필요가

증가하지 않고 값을 확인하는 atomicCounter(AC1)을 수행하지 않는 한 가지고 있습니다. 원자 적으로 값을 증가시키고 이전 값을 되 찾는 순간, 동일한 작업을 수행하는 다른 모든 사람 만이 증가 된 값을 얻게됩니다.

A- 버퍼를 수행하는 것처럼 보입니다. 왜 두 번째 카운터가 필요한지 궁금합니다. 나는 uimage1D_A가 uimage1D_B에 저장된 조각 목록에 대한 포인터의 화면 크기 맵이라고 가정합니다. 맞습니까? 당신은 uimage1D_B의 새로운 사용되지 않는 메모리 부분에 대한 포인터를 생성하는 AC2를 사용하지만 AC1은 점차 내가 완전히 잘못 :)

관련 문제