我对此有点坚定,因为我没有真正弄错了什么不是。必须有一些我极度误解的东西,或者在代码或驱动程序中都存在某种错误。我上周在AMD Radeon 5850上运行了最新的催化剂beta驱动程序。
好的,我开始执行OIT渲染实现,并希望使用保存在着色器存储缓冲区对象中的struct-array。好吧,那个中的索引在内存中反映/向前移动是错误的,我几乎认为这是一个驱动程序错误 - 因为他们刚刚开始支持这样的事情+是的,它是一个beta驱动程序。 因此,我向后移动了一个缺口并使用了纹理缓冲区对象中的glsl-images,我认为至少有一段时间以来它一直受到支持。
仍然表现不正常。所以我创建了一个简单的测试项目并且稍微摸了一下,现在我觉得我只是捏了一下这个东西。
OK!首先,我初始化缓冲区和纹理。
//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);
我只是放了一些内存障碍来确定,不应该伤害超过性能吗?好吧,无论如何,无论有没有障碍,结果都是一样的,所以......:)
Shader程序是一个简单的传递顶点着色器和正在进行测试的片段着色器。
顶点着色器
#version 430
in vec3 in_vertex;
void main(void)
{
gl_Position = vec4(in_vertex, 1.0);
}
片段着色器(我猜这里并不需要连贯&amp; memoryBarrier()因为我在CPU上执行绘制/片段着色器执行...但是它有害吗?)< / p>
#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-thing的东西让它变得渺茫,但这是一个逻辑的地方? :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);
,但我认为tbo
和tex
具有相同的值,因为它们是在同一个中生成的订购。因此它在这个实现中起作用。
我已经解决了这个问题,因为我认为上述内容应该有效,所以我对此并不满意。另一方面,新解决方案可能在性能方面更好一些。
我没有使用glMapBuffer()
,而是通过使用glBufferSubData()
和glgetBufferSubData()
在CPU / GPU之间发送数据来切换到在CPU上保留tbo内存的副本。这很有用,所以我将继续使用该解决方案。
但是,是的,问题仍然存在 - 为什么glMapBuffer()
不能处理纹理缓冲区对象?
答案 0 :(得分:3)
glTexBuffer(GL_TEXTURE_BUFFER,GL_RGBA32F,tex); 应该 glTexBuffer(GL_TEXTURE_BUFFER,GL_RGBA32F,tbo);
也许还有其他错误,但这很突出。 https://www.opengl.org/wiki/Buffer_Texture