我想知道内存函数在计算着色器中的工作原理。因此,正在尝试下面的代码。
使用NIVIDA OPENGL 4.3,GL 430。
计算着色器:
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
layout(std140, binding=1) buffer Res{
coherent int result;
};
void main()
{
int a=0;
result=1;
a = atomicAdd(result, 1);
//barrier();
//memoryBarrier()
}
在程序中,启动工作组
glGenBuffers(1, &bufferObj, nResult);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferObj);
glBufferData(GL_SHADER_STORAGE_BUFFER, 4, NULL, GL_DYNAMIC_READ);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, bufferObj);
glDispatchCompute(17,1,1);
glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
buffer = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
printf("value =%d", *buffer);
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
但是对于每次执行我都会得到'result'缓冲变量的随机值。想要使用记忆功能,但仍然无法正常工作。
获得正确的结果,直到num_groups_x = 16。此外,直到num_groups_x = 16,它在着色器中也不需要任何记忆功能。
答案 0 :(得分:1)
屏障功能将阻止着色器的调用超出某个点,直到所有调色板都到达它。它有效地影响调度以防止数据危害。否则,它们都将以GPU /驱动程序选择的任何偶然顺序执行。计算着色器实际上添加了一种新的屏障,用于仅同步同一工作组中着色器的调用,称为memoryBarrierShared。
顺便说一下,这是一个设置记忆障碍的愚蠢场所。字面上 没有 发生在障碍之后,所以我不明白你为什么要在那里添加同步点。通常,只有在需要确保着色器的所有其他调用都已完成load
之类的操作之前,才会在着色器级别引入内存障碍,然后再使用store
覆盖相同的资源。您以同步的名义引入了一个人工停顿。我指的是着色器中已注释的屏障。
现在,此代码中还有另一个问题,它根本与完全无关,可以解释您的问题。您正在从缓冲区对象(buffer = (GLint*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4, GL_MAP_READ_BIT);
)返回指向映射内存的指针,在对该指针执行任何操作之前,您将取消映射内存。因此,buffer
指向无效的内存,结果将是未定义的 - 您可能会崩溃您的程序或只是读取垃圾内存。
buffer
仅在映射时有效。
此外,在代码摘录的开头,buffer
是缓冲区对象的名称。在摘录的最后,它被用于存储指向内存的指针。 glGenBuffers (...)
在C语言绑定中也只占用2个参数。您的编译器在方向盘处于睡眠状态,您将此代码粘贴错误,或者这是除C之外的某种语言。