gpt4 book ai didi

opengl - 计算着色器共享内存包含工件

转载 作者:行者123 更新时间:2023-12-02 06:35:24 25 4
gpt4 key购买 nike

我一直在尝试编写一个通用计算着色器高斯模糊实现。

它基本上可以工作,但是它包含的伪影会改变每一帧,即使场景是静态的。我花了几个小时尝试调试这个。我已经尽力确保不超出界限,展开所有循环,用常量替换制服,但工件仍然存在。

我已经在 3 台不同的机器/GPU(2 个 nvidia、1 个 intel)上使用工件测试了原始代码,它们都产生相同的结果。使用纯 C++ 代码向前和向后执行的工作组来模拟代码执行的展开/恒定版本不会产生这些错误。

enter image description here

通过分配 [96][96] 而不是 [16][48] 的共享数组,我可以消除大多数工件。

这让我认为我错过了一个逻辑错误,因此我设法生成了一个非常简单的着色器,它仍然在较小范围内产生错误,如果有人能指出原因,我将不胜感激。我检查了很多文档,没有发现任何不正确的地方。

分配了 16x48 float 的共享数组,即 3072 字节,大约是最小共享内存限制的 10%。

着色器在 16x16 工作组中启动,因此每个线程将写入 3 个唯一位置,并从单个唯一位置读回

然后纹理将渲染为 HSV,其中 0-1 之间的值将映射到色调 0-360(红-青-红),超出范围的值将为红色。

#version 430
//Execute in 16x16 sized thread blocks
layout(local_size_x=16,local_size_y=16) in;
uniform layout (r32f) restrict writeonly image2D _imageOut;
shared float hoz[16][48];
void main ()
{
//Init shared memory with a big out of bounds value we can identify
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 20000.0f;
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 20000.0f;
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 20000.0f;
//Sync shared memory
memoryBarrierShared();
//Write the values we want to actually read back
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 0.5f;
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 0.5f;
hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 0.5f;
//Sync shared memory
memoryBarrierShared();
//i=0,8,16 work
//i=1-7,9-5,17 don't work (haven't bothered testing further
const int i = 17;
imageStore(_imageOut, ivec2(gl_GlobalInvocationID.xy), vec4(hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+i]));
//Sync shared memory (can't hurt)
memoryBarrierShared();
}

启动尺寸大于 8x8 的着色器会在图像的受影响区域中产生伪影。


glDispatchCompute(9, 9, 0);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

我必须设置断点和单步帧来捕获此图像,大约需要 14 帧 enter image description here


glDispatchCompute(512/16, 512/16, 0);//全图为512x512
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

我再次必须断点和步进帧来捕捉这一点,当以 60FPS(垂直同步)运行时,伪像出现得更频繁/同时。

enter image description here

最佳答案

memoryBarrierShared();

不,这只会使写入对其他调用可见。如果您希望能够从其他调用的数据中读取数据,则必须确保所有写入均已实际发生

这是用 the barrier function 完成的。应该在 memoryBarrierShared之后调用它。

关于opengl - 计算着色器共享内存包含工件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41175954/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com