首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >InterlockedSubtract解决方案-内存屏障

InterlockedSubtract解决方案-内存屏障
EN

Stack Overflow用户
提问于 2022-02-17 11:59:39
回答 1查看 113关注 0票数 0

我遇到了一种情况,我希望在HLSL中有一个InterlockedSubtract函数。InterlockedAdd对于整数很好,但是我只能使用uint的RWByteAddressBuffer --我使用的是每一个位,我不希望使用一个编码/解码函数来使ints的行为与uint完全一样。

我目前的解决办法如下:

代码语言:javascript
复制
uint oldValue = Source.Load(oldParent, y);
Source.InterlockedMin(oldParent, oldValue - 1, y);

问题是,我理解这些操作有可能在几个线程中被混淆,如下所示:

代码语言:javascript
复制
Thread 1:                   Thread 2:
o1 = Source.Load(l)                                                      l = 10, o1 = 10
                            o2 = Source.Load(l)                          l = 10, o2 = 10
Source.InterlockedMin(l, o1 - 1)                                         l = 9
                            Source.InterlockedMin(l, o2 - 1)             l = 9

尽管有两个调用,但这些值只会减少一次。

据我所知,我不能把它变成一条直线,因为编译后的指令无论如何都可以去同步。

有什么办法我错过了吗?我可以重构我的代码,使用另一个uint作为减法计数器,然后使用另一个内核从实际计数中减去这些,但是我更愿意将它保存在一个内核中。

EN

回答 1

Stack Overflow用户

发布于 2022-02-22 13:06:01

谢谢,彼得考兹,你说得很对。我做了一些非常简单的测试:

HLSL

代码语言:javascript
复制
#pragma kernel Overflow

RWByteAddressBuffer buff;

uint ByteIndex(uint3 id)
{
    return (id.x + id.y * 8) * 4;
}

[numthreads(8,8,1)]
void Overflow (uint3 id : SV_DispatchThreadID)
{
    uint originalValue;
    buff.InterlockedAdd(ByteIndex(id), 1, originalValue);
}

和C#

代码语言:javascript
复制
    public ComputeShader shade;
    private ComputeBuffer b;
    private int kernel;
    private uint[] uints = new uint[64];

    private void Start()
    {
        for(int i = 0; i < 64; i++) { uints[i] = 4294967294; }
        for(int i = 0; i < 64; i++) { Debug.Log(uints[i]); }
    }

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            b = new ComputeBuffer(64, sizeof(uint));
            b.SetData(uints);
            kernel = shade.FindKernel("Overflow");
            shade.SetBuffer(kernel, Shader.PropertyToID("buff"), b);
            shade.Dispatch(kernel, 1, 1, 1);
            b.GetData(uints);
            b.Dispose();
            for (int i = 0; i < 64; i++) { Debug.Log(uints[i]); }
        }        
    }

这清楚地表明了所期望的行为。

如果在HLSL中记录了这种行为,那就太好了,但至少我现在知道了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71157748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档