2013-04-25 2 views
2

누군가 DirectX 11에서 다음과 같은 계산 쉐이더를 사용할 수 있는지 알려줄 수 있습니까?계산 쉐이더 : 한 스레드에서 다른 스레드로 쓰여진 데이터를 읽으시겠습니까?

버퍼 (g_positionsGrid)의 요소에 액세스하여 해당 요소를 임시 값과 설정 (비교 교환)하는 첫 번째 스레드가 어떤 조치를 취하고 있음을 나타 내기 원합니다.

이 경우 임시 값은 0xffffffff이며 첫 번째 스레드는 계속 진행하고 구조화 된 추가 버퍼 (g_positions)에서 값을 할당하고이를 해당 요소에 할당합니다.

그래도 괜찮지 만 디스패치의 다른 스레드는 비교 교환과 첫 번째 스레드의 할당 사이에 들어올 수 있으므로 할당 인덱스를 사용할 수있을 때까지 기다려야합니다. 나는 바쁜 기다림 즉 while 루프로 이것을한다.

슬프게도 이것은 첫 번째 스레드에서 작성한 값이 while 루프에 걸린 다른 스레드로 전달되지 않는다고 가정 할 때 GPU를 잠급니다.

해당 스레드에서 해당 값을 볼 수있는 방법이 있습니까?

도움 주셔서 감사합니다.

RWStructuredBuffer<float3> g_positions : register(u1); 
RWBuffer<uint> g_positionsGrid : register(u2); 

void AddPosition(uint address, float3 pos) 
{ 
    uint token = 0; 

    // Assign a temp value to signify first thread has accessed this particular element 
    InterlockedCompareExchange(g_positionsGrid[address], 0, 0xffffffff, token); 

    if(token == 0) 
    { 
     //If first thread in here allocate index and assign value which 
     //hopefully the other threads will pick up 
     uint index = g_positions.IncrementCounter(); 
     g_positionsGrid[address] = index; 
     g_positions[index].m_position = pos; 
    } 
    else 
    { 
     if(token == 0xffffffff) 
     { 
      uint index = g_positionsGrid[address]; 

      //This never meets its condition 
      [allow_uav_condition] 
      while(index == 0xffffffff) 
      { 
       //For some reason this thread never gets the assignment 
       //from the first thread assigned above 
       index = g_positionsGrid[address]; 
      } 

      g_positions[index].m_position = pos; 
     } 
     else 
     { 
      //Just assign value as the first thread has already allocated a valid slot 
      g_positions[token].m_position = pos; 

     } 
    } 
} 

답변

2

DirectCompute의 스레드 동기화는 매우 쉽지만 CPU 스레딩과 동일한 기능을 비교하는 것은 매우 융통성이 없습니다. AFAIK는 컴퓨팅 쉐이더에서 스레드간에 데이터를 동기화하는 유일한 방법은 groupshared 메모리와 GroupMemoryBarrierWithGroupSync()을 사용하는 것입니다.

  • 다른 스레드 사용에서 groupshared에서 읽을 GroupMemoryBarrierWithGroupSync()
  • 와 스레드를 동기화 groupshared 메모리
  • 계산 값
  • 쓰기 버퍼 groupshared에 작은 임시 버퍼를 만들 : 그것은 당신이 할 수있는, 의미 그것도 어떻게 든

이 모든 것을 구현하려면 다음과 같이하십시오. n 적절한 배열 색인을 작성하십시오. 그러나 어디에서 그것을 가져갈 수 있습니까? DirectCompute 값은 Dispatch으로 전달되고 쉐이더 (SV_GroupIndex, SV_DispatchThreadID, SV_GroupThreadID, SV_GroupID)에서 얻을 수있는 시스템 값은 related입니다. 이 값을 사용하여 인덱스를 계산하여 버퍼를 평가할 수 있습니다.

계산 쉐이더는 잘 설명되지 않으며, 쉬운 방법이 없다, 그러나 적어도 할 수 있습니다 더 많은 정보를 알아 :

코드 기준. 음, 아마도 당신은 조금 재 설계 할 수 있습니다.

  1. 모든 스레드가 동일한 작업을 수행하는 것이 좋습니다. 대칭 적재. 실제로 CPU 코드 에서처럼 스레드에 다른 작업을 할당 할 수 없습니다.

  2. 데이터가 먼저 몇 가지 전처리 및 추가 처리가 필요하면, 당신은 당신이 순서대로 호출 differrent 파견() 호출 (다른 쉐이더)로 나눌 수 있습니다

    • preprocessShader

      버퍼에서 읽어 inputDatapreprocessedData에서 preprocessedData
    • calculateShader feads에 기록이 경우 finalData

    에 기록 요 느린 스레드 동기화 및 느린 그룹 공유 메모리를 삭제할 수 있습니다.

  3. 위에서 언급 한 "줄이기"트릭을보십시오.

희망 하시겠습니까? 그리고 행복한 코딩!