有人可以告诉我以下计算着色器是否可以用于 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;
}
}
}
DirectCompute 中的线程同步非常容易,但与 CPU 线程的相同功能相比非常不灵活。 AFAIK,在计算着色器中的线程之间同步数据的唯一方法是使用
groupshared
内存和 GroupMemoryBarrierWithGroupSync()
。这意味着您可以:
groupshared
内存中创建小型临时缓冲区groupshared
缓冲区GroupMemoryBarrierWithGroupSync()
groupshared
并以某种方式使用它要实现所有这些东西,您需要适当的数组索引。但你可以从哪里获取它呢?在 DirectCompute 中,传入Dispatch的值以及您可以在着色器中获取的系统值(SV_GroupIndex、SV_DispatchThreadID、SV_GroupThreadID、SV_GroupID)相关。使用该值,您可以计算索引来评估您的缓冲区。
计算着色器没有很好的文档记录,并且没有简单的方法,但要查找更多信息至少可以:
从你的代码开始。好吧,也许你可以稍微重新设计一下。
所有线程执行相同的任务总是好的。对称加载。实际上,您不能像在 CPU 代码中那样为线程分配不同的任务。
如果您的数据首先需要进行一些预处理,然后进一步处理,您可能需要将其划分为按顺序调用的不同 Dispatch() 调用(不同的着色器):
preprocessShader
从缓冲区 inputData
读取并写入 preprocessedData
calculateShader
从 preprocessedData
馈送并写入 finalData
在这种情况下,您可以放弃任何慢速线程同步和慢速组共享内存。
看看上面提到的“线程减少”技巧。
希望有帮助!祝您编码愉快!
我只是来这里问你如何从计算着色器中的追加缓冲区读取数据?您声明 g_positions 是一个追加缓冲区,并通过引用索引 (g_positions[value]) 在代码中访问它。您是否首先在不同的计算着色器中附加到此缓冲区?我目前正在尝试了解如何追加到追加缓冲区,然后在计算着色器中读取该追加缓冲区,而无需传递到 cpu?