2013-04-25 58 views
2

有人可以告诉我DirectX 11是否可以使用以下计算着色器?计算着色器:读取从另一个线程写入的数据?

我想要一个Dispatch中的第一个线程访问缓冲区(g_positionsGrid)中的元素来设置(比较交换)该元素与临时值来表示它正在采取一些行动。

在这种情况下,临时值为0xffffffff,第一个线程将继续运行,并从结构化追加缓冲区(g_positions)分配一个值并将其分配给该元素。

因此,目前为止所有罚款,但调度中的其他线程可以进入比较交换和第一个线程的分配之间,因此需要等到分配索引可用。我在忙着等待,即while循环。

然而遗憾的是,这只是锁定了GPU,因为我假设第一个线程写入的值不会传播到while循环中的其他线程。

有没有什么办法让这些线程看到这个值?

感谢您的帮助!

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内存
  • 计算值
  • groupshared缓冲
  • 同步与GroupMemoryBarrierWithGroupSync()
  • 线程从另一个线程和使用来自groupshared读创建小的临时缓冲区它不知何故

要实现所有这些东西,你n eed正确的数组索引。但是,你可以从哪里拿走?在Dispatch中传递的DirectCompute值以及可在着色器中获得的系统值(SV_GroupIndex,SV_DispatchThreadID,SV_GroupThreadID,SV_GroupID)related。使用这个值你可以计算指数来评估你的缓冲区。

计算着色器都有详细的记载,并没有简单的方法,但要找出更多信息至少你可以:

从您的代码开始。那么,可能你可以重新设计一点。

  1. 对于所有线程来说,做同样的任务总是好的。对称加载。实际上,你不能像CPU代码那样为你的线程分配不同的任务。

  2. 如果你的数据首先需要一些预处理和进一步的加工,你可能希望把它划分到differrent调度()调用(不同的着色器),您将依次拨打:

    • preprocessShader从缓冲区中读取inputData和写入preprocessedData
    • calculateShader feads从preprocessedData和写入finalData

    在这种情况下哟你可以退出任何慢线程同步和慢组共享内存。

  3. 看看上面提到的“减少线程”的技巧。

希望它有帮助!和快乐的编码!

相关问题