2013-10-08 68 views
6

因为我没有真正明白什么是错的,什么不是什么,所以我对此有点疯狂。必须有一些我被大大误解的东西,或者代码或驱动程序中存在某种错误。我在上周使用最新的催化剂测试版驱动程序在AMD Radeon 5850上运行。读取和更新OpenGL/GLSL中的纹理缓冲区4.3

好吧,我开始做一个OIT渲染实现,并希望使用保存在着色器存储缓冲区对象中的结构数组。那么,那个指数在记忆方面反映/推进是错误的,我很认为这是一个驱动程序错误 - 因为他们刚刚开始支持这样的事情,是的,它是一个测试版驱动程序。 因此,我移回了一个凹槽,并使用纹理缓冲区对象中的glsl-images,而我至少在一段时间后认为它已经被支持。

仍然表现不正确。所以我创建了一个简单的测试项目并且摸索了一下,现在我认为我只是捏住了事情的位置。

行!首先我初始化的缓冲区和纹理。

//Clearcolor and Cleardepth setup, disabling of depth test, compile and link shaderprogram etc. 
... 
// 
GLint tbo, tex; 
datasize = resolution.x * resolution.y * 4 * sizeof(GLfloat); 
glGenBuffers(1, &tbo); 
glBindBuffer(GL_TEXTURE_BUFFER, tbo); 
glBufferData(GL_TEXTURE_BUFFER, datasize, NULL, GL_DYNAMIC_COPY); 
glBindBuffer(GL_TEXTURE_BUFFER, 0); 

glGenTextures(1, &tex); 
glBindTexture(GL_TEXTURE_BUFFER, tex); 
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); 
glBindTexture(GL_TEXTURE_BUFFER, 0); 
glBindImageTexture(2, tex, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA32F); 

然后,渲染循环是 - 更新和绘制,更新和绘制...在两者之间的延迟,使我有时间看看更新的作用。

更新是这样的...

ivec2 resolution; //Using GLM 
resolution.x = (GLuint)(iResolution.x + .5f); 
resolution.y = (GLuint)(iResolution.y + .5f); 

glBindBuffer(GL_TEXTURE_BUFFER, tbo); 
void *ptr = glMapBuffer(GL_TEXTURE_BUFFER, GL_WRITE_ONLY); 
color *c = (color*)ptr; //color is a simple struct containing 4 GLfloats. 
for (int i = 0; i < resolution.x*resolution.y; ++i) 
{ 
    c[i].r = c[i].g = c[i].b = c[i].a = 1.0f; 
} 
glUnmapBuffer(GL_TEXTURE_BUFFER); c = (color*)(ptr = NULL); 
glBindBuffer(GL_TEXTURE_BUFFER, 0); 

而且是这样的...

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glMemoryBarrier(GL_ALL_BARRIER_BITS); 
ShaderProgram->Use(); //Simple shader program class 
quad->Draw(GL_TRIANGLES); //Simple mesh class containing triangles (vertices) and colors 
glFinish(); 
glMemoryBarrier(GL_ALL_BARRIER_BITS); 

我只是把周围的一些记忆力障碍要格外肯定,不应该损害超过表演权吗?那么,无论如何,结果是有或没有障碍,所以... :)

着色器程序是一个简单的传递顶点着色器和片段着色器正在做测试。

顶点着色器

#version 430 

in vec3 in_vertex; 

void main(void) 
{ 
    gl_Position = vec4(in_vertex, 1.0); 
} 

片段着色器(我猜的连贯&内存屏障()是不是真的在这里需要的,因为我在抽签/片段着色器执行之间做他们的CPU ......但它伤害)

#version 430 

uniform vec2 iResolution; 
layout(binding = 2, rgba32f) coherent uniform imageBuffer colorMap; 

out vec4 FragColor; 

void main(void) 
{ 
    ivec2 res = ivec2(int(iResolution.x + 0.5), int(iResolution.y + 0.5)); 
    ivec2 pos = ivec2(int(gl_FragCoord.x + 0.5), int(gl_FragCoord.y + 0.5)); 
    int pixelpos = pos.y * res.x + pos.x; 

    memoryBarrier(); 
    vec4 prevPixel = imageLoad(colorMap, pixelpos); 

    vec4 green = vec4(0.0, 1.0, 0.0, 0.0); 
    imageStore(colorMap, pixelpos, green); 
    FragColor = prevPixel; 
} 

期望:白色屏幕!由于我在每次绘制之间为整个缓冲区写入“白色”,即使在实际着色器中加载后我正在写入绿色图像。

结果:第一帧为绿色,其余为黑色。我的某些部分认为,有一个白色的框架太快,不能被看到或一些vsync的东西,它可以看到,但它是一个逻辑的地方? :P

那么,我尝试了一个新的东西,并将更新块(我正在写入“白色”到整个缓冲区)移动到init。

期望值:白色第一帧,后面是绿色屏幕。

结果:哦,是的,它的绿色所有权!即使第一帧有一些白色/绿色的文物,有时也只是绿色。这可能是由于(缺少)vsync的东西,没有检查出来。不过,我想我得到了我正在寻找的结果。

我可以从中得出的结论是,我的更新中有些问题。 它是否从纹理参考中解开缓冲区?在这种情况下,第一帧可以吗?它只是在第一个imageStore命令(以及第一帧)之后纹理全部变黑 - “bind() - map() - unmap() - bind(0)”之后才起作用,但之后不起作用。 我的glMapBuffer的图片是它将GPU中的缓冲区数据复制到CPU内存,让我们改变它,然后Unmap将它复制回来。那么,刚才我想,也许它不会将GPU的缓冲区复制到CPU然后回来,但只有一种方法?它可能是GL_WRITE_ONLY应该改为GL_READ_WRITE吗?好吧,我已经试过了。据说其中一个是正确的,当我使用那个时,我的屏幕总是在“测试1”中是白色的?

ARGH,我做错了什么?

编辑: 好了,我还是不知道......显然glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex);glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);,但我认为tbotex有相同的价值,因为他们在相同的顺序产生。因此它在这个实现中起作用。 虽然我已经解决了,但我并不满意,因为我真的认为上述方法可行。另一方面,新解决方案可能会在性能方面更好一些。 而不是使用glMapBuffer(),我转而使用glBufferSubData()glgetBufferSubData()在CPU/GPU之间发送数据,以保留CPU上的tbo存储器的副本。这工作,所以我会继续解决方案。

但是,是的,问题仍然存在 - 为什么glMapBuffer()不能用于我的纹理缓冲区对象?

回答