2013-10-08 3 views
6

Я собираюсь немного рассердиться на это, так как я действительно не понимаю, что не так, а что нет. Должно быть либо что-то, что я слишком неправильно понял, либо есть какая-то ошибка в коде или в драйвере. Я запускаю это на AMD Radeon 5850 с последними драйверами бета-версии драйверов на прошлой неделе.Чтение и обновление буфера текстур в OpenGL/GLSL 4.3

ОК, я начал выполнять реализацию рендеринга OIT и хотел использовать структурный массив, сохраненный в объекте буфера хранилища шейдеров. Ну, индексы в этом отражают/двигаются вперед по памяти неправильно, и я в значительной степени предполагал, что это ошибка драйвера - так как они совсем недавно начали поддерживать такую ​​вещь + да, это бета-драйвер. Поэтому я переместился назад на метку и вместо этого использовал glsl-изображения из объектов текстурного буфера, которые, как я полагаю, поддерживались, по крайней мере, некоторое время назад.

Все еще не вел себя правильно. Поэтому я создал простой тестовый проект и немного пошарил, и теперь я думаю, что я просто ущипнул, где это все.

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 - это простой проходной шейдер вершин и шейдер фрагмента, который проводит тестирование.

Vertex шейдер

#version 430 

in vec3 in_vertex; 

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

Фрагмент шейдеры (я предполагаю, когерентное & 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: белый экран! Поскольку я пишу «белый» для всего буфера между каждой ничью, даже если я пишу зеленым изображение после загрузки в фактическом шейдере.

Результат: Первый кадр зеленый, остальные черные. Некоторая часть меня думает, что есть белая рамка, которая слишком быстро, чтобы ее можно было увидеть, или какая-то vsync-вещь, которая плести его, но это место для логики? : P

Ну, тогда я попробовал новую вещь и переместил блок обновления (где я пишу «белый» во весь буфер) вместо init.

Ожидание: белый первый кадр, за которым следует зеленый экран.

Результат: О да, зеленый цвет! Хотя первый кадр с некоторыми артефактами белого/зеленого, иногда только зеленого. Возможно, это связано с (отсутствием) vsync чего-то, не проверил это. Тем не менее, я думаю, что получил результат, который я искал.

Вывод, который я могу сделать из этого, заключается в том, что в моем обновлении что-то не так. Отбрасывает ли буфер из ссылки на текстуру или что-то в этом роде? В этом случае, не странно, что первый кадр в порядке? Только после первой команды imageStore (ну, в первом кадре) текстура становится черной - «bind() - map() - unmap() - bind (0)» работает в первый раз, но не после. Моя картинка glMapBuffer заключается в том, что она копирует данные буфера с графического процессора в память процессора, давайте изменим его и Unmap скопирует его обратно. Ну, теперь я подумал, что, возможно, он не копирует буфер с GPU на CPU, а затем обратно, но только один способ? Может ли быть GL_WRITE_ONLY, который должен быть изменен на GL_READ_WRITE? Ну, я попробовал оба. Предположительно, один из них был прав, не будет ли мой экран при использовании этого, который всегда будет белым в «тесте 1»?

ARGH, что я делаю неправильно?

EDIT: Ну, я до сих пор не знаю ... Очевидно glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tex); должно быть glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo);, но я думаю, что tbo и tex имел такое же значение, так как они были получены в том же порядке. Поэтому он работал в этой реализации. Я решил это, хотя, в некотором роде, я не очень доволен, так как я действительно думаю, что вышеприведенное должно работать. С другой стороны, новое решение, вероятно, немного лучше по производительности. Вместо того, чтобы использовать glMapBuffer(), я переключился на сохранение копии ТВ-памяти на CPU с помощью glBufferSubData() и glgetBufferSubData() для отправки данных между CPU/GPU. Это сработало, поэтому я просто продолжу это решение.

Но, вопрос все еще стоит - Почему glMapBuffer() не работает с моими объектами буфера текстуры?

ответ

Смежные вопросы