I'm going to get a little angry at this because I really don't understand what is wrong and what is not. There must be something that I misunderstood, or there is some kind of error in the code or in the driver. I am running this on an AMD Radeon 5850 with the latest beta drivers last week.
OK, I started implementing the OIT rendering and wanted to use a structural array stored in the shader storage buffer object. Well, the indices in this reflect / move forward in memory incorrectly, and I pretty much assumed that this was a driver error - since they recently started supporting such a thing + yes, this is a beta driver. So I moved back to the label and instead used glsl images from texture buffer objects, which I believe were supported at least some time ago.
Still not behaving correctly. So I created a simple test project and fumbled a bit, and now I think that I just pinched where it was.
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 cycle is updating and drawing, updating and drawing ... With a delay between them, so that I have time to see what the update does.
The update is as follows:
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 draw looks 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 sure if there should be more harm than performance? Well, the result was the same with or without barriers anyway, so ... :)
The Shader program is a simple vertex shader and fragment shader that performs testing.
Vertex shader
#version 430 in vec3 in_vertex; void main(void) { gl_Position = vec4(in_vertex, 1.0); }
Fragment shader (I think that coherent and memoryBarrier () are not really needed here, since I do them on the processor between the execution of the shader / shader fragment ... but is it harmful?)
Waiting : white screen! Because I write “white” for the entire buffer between each draw, even if I write a green image after loading in the actual shader.
Result . The first frame is green, the rest are black. Some part of me thinks that there is a white frame that is too fast to be seen, or some kind of vsync-thing that weave it, but this is the place for logic ?: P
Well, then I tried a new thing and moved the update block (where I write “white” for the entire buffer) instead of init.
Waiting : first white frame followed by a green screen.
Result : Oh yes, its green! Although the first frame with some artifacts is white / green, sometimes only green. Perhaps this is due to the (lack of) vsync of something, did not check it. However, I think I got the result I was looking for.
I can conclude that something is wrong with my update. Does it drop the buffer from the texture link or something else? In this case, is it not strange that the first frame is ok? It is only after the first imageStore command (well, the first frame) that the texture goes in black - "bind () - map () - unmap () - bind (0)" works for the first time, but not after. My glMapBuffer picture is that it copies the buffer data from the GPU to the processor memory, allows you to modify it and Unmap copies it back. Well, now I thought that maybe it is not copying the buffer from the GPU to the CPU and then back, but only one way? Could there be GL_WRITE_ONLY that needs to be changed to GL_READ_WRITE? Well, I tried both. Presumably, one of them was right, would my screen not always be white when using “test 1”?
ARGH, what am I doing wrong?
EDIT: Well, I still don't know ... Obviously glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); must be glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); , but I think tbo and tex had the same meaning, since they were generated in the same order. Therefore, he worked in this implementation. I solved this, although in this way I am not very happy, as I really think the above should work. On the other hand, the new solution is probably a little better in performance. Instead of using glMapBuffer() I switched to saving a copy of the TAB memory to the CPU using glBufferSubData() and glgetBufferSubData() to send data between the CPU / GPU. It worked, so I will just continue this decision.
But, yes, the question is still standing. Why glMapBuffer() not work with my texture buffer objects?