简体   繁体   English

在OpenGL / GLSL 4.3中读取和更新纹理缓冲区

[英]Reading and updating texture buffer in OpenGL/GLSL 4.3

I'm going a bit nuts on this since I don't really get what is wrong and what not. 我对此有点坚定,因为我没有真正弄错了什么不是。 There must either be something that I've vastly misunderstood or there is some kind of bug either in the code or in the driver. 必须有一些我极度误解的东西,或者在代码或驱动程序中都存在某种错误。 I'm running this on AMD Radeon 5850 with the latest catalyst beta drivers as of last week. 我上周在AMD Radeon 5850上运行了最新的催化剂beta驱动程序。

OK, I began doing a OIT-rendering implementation and wanted to use a struct-array saved in a shader storage buffer object. 好的,我开始执行OIT渲染实现,并希望使用保存在着色器存储缓冲区对象中的struct-array。 Well, the indices in that one were reflecting/moving forward in memory way wrong and I pretty much assumed that it was a driver bug - since they just recently started supporting such thing + yeah, it's a beta driver. 好吧,那个中的索引在内存中反映/向前移动是错误的,我几乎认为这是一个驱动程序错误 - 因为他们刚刚开始支持这样的事情+是的,它是一个beta驱动程序。 Therefore I moved back a notch and used glsl-images from texture buffer objects instead, which I guess had been supported since at least a while back. 因此,我向后退了一个档位并使用了来自纹理缓冲区对象的glsl-images,我想至少有一段时间以来一直支持它们。

Still wasn't behaving correctly. 仍然表现不正常。 So I created a simple test project and fumbled around a bit and now I think I've just pinched where the thing is. 所以我创建了一个简单的测试项目并且稍微摸了一下,现在我觉得我只是捏了一下这个东西。

OK! 好! First I initialize the buffer and texture. 首先,我初始化缓冲区和纹理。

//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);

Then the rendering loop is - update and draw, update and draw ... With a delay in between so that I have time to see what the update does. 然后渲染循环 - 更新并绘制,更新和绘制......两者之间有延迟,以便我有时间查看更新的作用。

The update is like this... 更新是这样的......

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);

And the draw is like this... 抽签是这样的......

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);

I just put some memory barriers around to be extra sure, shouldn't harm more than performance right? 我只是把一些记忆障碍放在一边更加确定,不应该伤害超过表现吗? Well, the outcome was the same with or without the barriers anyway, so ... :) 好吧,无论如何,无论有没有障碍,结果都是一样的,所以...... :)

The Shader program is a simple pass-through vertex shader and the fragment shader that's doing the testing. Shader程序是一个简单的传递顶点着色器和正在进行测试的片段着色器。

Vertex shader 顶点着色器

#version 430

in vec3 in_vertex;

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

Fragment shader (I guess coherent & memoryBarrier() isn't really needed here since I do them on CPU in between draw/fragment shader execution... but does it harm?) 片段着色器 (我猜这里并不需要连贯&memoryBarrier()因为我在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;
}

Expectation : A white screen! 期待 :白屏! Since I'm writing "white" to the whole buffer between every draw even if I'm writing green to the image after load in the actual shader. 因为我在每次绘制之间写入“白色”到整个缓冲区,即使我在实际着色器中加载后向图像写入绿色。

Result : The first frame is green, the rest is black. 结果 :第一帧为绿色,其余为黑色。 Some part of me thinks that there is a white frame thats too fast to be seen or some vsync-thing that tares it, but it this a place for logics? 我的某些部分认为有一个白色的框架太快而无法看到,或者有一些vsync-thing的东西让它变得渺茫,但这是一个逻辑的地方? :P :P

Well, then I tried a new thing and moved the update block (where i'm writing "white" to the whole buffer) to the init instead. 那么,我尝试了一个新的东西,并将更新块(我正在写“白色”到整个缓冲区)移动到init。

Expectation : A white first frame, followed by a green screen. 期望 :白色的第一帧,然后是绿色屏幕。

Result : Oh yes its green allright! 结果 :哦,是的它绿色好吧! Even though the first frame is with some artifacts of white/green, sometimes only green. 即使第一帧有一些白色/绿色的文物,有时只有绿色。 This might probably be due to (lack of) vsync of something, haven't checked that out. 这可能是由于某些东西的(缺乏)vsync,没有检查出来。 Still, I think I got the result I was looking for. 不过,我想我得到了我想要的结果。

The conclusion I can draw out of this is that there is something wrong in my update. 我可以得出的结论是我的更新中出现了问题。 Does it unhook the buffer from the texture reference or something? 它是否从纹理参考中取消了缓冲区或其他东西? In that case, isn't it weird that the first frame is OK? 在那种情况下,第一帧是否正常并不奇怪? It's only after the first imageStore-command (well, the first frame) that the texture goes all black - the "bind()-map()-unmap()-bind(0)" works the first time, but not afterwards. 只有在第一个imageStore命令(嗯,第一帧)之后,纹理全部变黑 - “bind() - map() - unmap() - bind(0)”第一次工作,但之后不工作。 My picture of glMapBuffer is that it copies the buffer data from GPU to CPU memory, let's you alter it and Unmap copies it back. 我的glMapBuffer图片是它将缓冲区数据从GPU复制到CPU内存,让你改变它,Unmap将它复制回来。 Well, just now I thought that maybe it doesn't copy the buffer from GPU to CPU and then back, but only one way? 好吧,刚才我想也许它不会将缓冲区从GPU复制到CPU再返回,但只有一种方式? Could it be the GL_WRITE_ONLY which should be changed to GL_READ_WRITE? 可能是GL_WRITE_ONLY应该更改为GL_READ_WRITE吗? Well, I've tried both. 好吧,我试过了两个。 Supposedly one of them was correct, wouldn't my screen when using that one always be white in "test 1"? 据说其中一个是正确的,使用那个时我的屏幕不会在“测试1”中一直是白色的吗?

ARGH, what am I doing wrong? ARGH,我做错了什么?

EDIT: Well, I still don't know... Obviously glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); 编辑:嗯,我还是不知道......显然glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); should be glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); 应该是glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); , but I think tbo and tex had the same value since they were generated in the same order. ,但我认为tbotex具有相同的值,因为它们是以相同的顺序生成的。 Therefore it worked in this implementation. 因此它在这个实现中起作用。 I have solved it though, in a manner I'm not very happy with since I really think that the above should work. 我已经解决了这个问题,因为我认为上述内容应该有效,所以我对此并不满意。 On the other hand, the new solution is probably a bit better performance-wise. 另一方面,新解决方案可能在性能方面更好一些。 Instead of using glMapBuffer() , I switched to keeping a copy of the tbo-memory on CPU by using glBufferSubData() and glgetBufferSubData() for sending the data between CPU/GPU. 我没有使用glMapBuffer() ,而是通过使用glBufferSubData()glgetBufferSubData()在CPU / GPU之间发送数据来切换到在CPU上保留tbo内存的副本。 This worked, so I'll just continue with that solution. 这很有用,所以我将继续使用该解决方案。

But, yeah, the question still stands - Why doesn't glMapBuffer() work with my texture buffer objects? 但是,是的,问题仍然存在 - 为什么glMapBuffer()不能使用我的纹理缓冲区对象?

glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); glTexBuffer(GL_TEXTURE_BUFFER,GL_RGBA32F,tex); should be glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); 应该是glTexBuffer(GL_TEXTURE_BUFFER,GL_RGBA32F,tbo);

perhaps there is something else wrong, but this stands out. 也许还有其他问题,但这很突出。 https://www.opengl.org/wiki/Buffer_Texture https://www.opengl.org/wiki/Buffer_Texture

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM