LINUX.ORG.RU

Считывание из буфера кадров возвращает чёрный квадрат.

 ,


0

1

Задача: переместить буфер из основной памяти в память видеокарты и считать её обратно. Важно чтобы входной буфер полностью совпадал с выходным.

(Это я пытаюсь разобраться как работает GPGPU. Первый этап — обмен данными с видеокартой)

Как я понял, запись картинки можно сделать glTexImage2D(), а считать обратно с помощью glReadPixels(). Оба вызова срабатывают без ошибок, но обратно мне возвращается чёрный экран.

Мой код лежит (тут). Основная часть:

     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(dpy, &majorVersion, &minorVersion);
     eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs);
     EGLint attribs[] = { EGL_WIDTH, w, EGL_HEIGHT, h, EGL_NONE };
     surface = eglCreatePbufferSurface(dpy, config, attribs);
     context = eglCreateContext(dpy, config, NULL, NULL);
     eglMakeCurrent(dpy, surface, surface, context);
     eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
     eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
     glViewport(0, 0, w, h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     glOrthof(0, w, 0, h, 0, 1); 
     glBindTexture(GL_TEXTURE_2D, 0);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     // *** data = { 0, 10, 20, 30, ... }
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
         texSize, texSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
     glReadPixels(0, 0, texSize, texSize, GL_RGBA,
             GL_UNSIGNED_BYTE, result);
     // *** result теперь такой: {0,0,0,255,0,0,0,255,...}

Как сделать так чтобы содержимое result полностью совпадало с исходной data? Есть ли более оптимальный путь достичь этого же результата, если в дальнейшем я захочу использовать шейдер для работы с буфером?



Последнее исправление: mors (всего исправлений: 1)

чтобы текстура попала в фреймбуфер нужно, чтобы она «натянулась» на примитив.

x4DA ★★★★★
()
Ответ на: комментарий от x4DA

Можешь написать в каком направлении гуглить? Как лучше всего обмениваться большими объёмами данных между шейдерным кодом на GPU и основной программой на CPU?

mors
() автор топика

мясо какое-то:) сначала просить систему выдать гл-контекст, потом уже делать; а то у меня сигсегв, скорее всего глес первой версии отказывается работать.

sanaris
()
Ответ на: комментарий от sanaris

Вся инициализация (egl*) содрана с frameworks/base/opengl/tests/test-opengl-filter (Android). И собственно на андройде это вроде как работает без падений.

Хотя признаюсь что с opengl я ни в зуб ногой. Первые эксперименты так сказать...

mors
() автор топика

Малевич, однако!

А вообще, советую OpenGL Book почитать. Т.к. буфер-то пустой, пока его не заполнишь!

А текстуры без заполнения буфера работают лишь в куде.

Eddy_Em ☆☆☆☆☆
()

Советую почитать про FramebufferObject.

Dendy ★★★★★
()
Ответ на: комментарий от x4DA

для таких как ты придумали opencl и cuda.

если уж так хочется gpgpu, то выше уже все расписали.

Поддерживаю, сейчас такие велосипеды будут не просто сложнее, они еще и намного медленнее будут, поскольку CUDA/OpenCL намного оптимизированней.

ТС, почитай David B.Kirk, Wen-mei W.Hwu — Programming Massively Parallel Processors, A Hands-on Approach.

unfo ★★★★★
()
Ответ на: Малевич, однако! от Eddy_Em

:)

Добавив glEnable(GL_TEXTURE_2D); (не знаю зачем это нужно) и glDrawTexiOES(0, 0, 1, texSize, texSize); (собственно рисование текстуры), мне удалось записать и считать 4 байта :)

Правда эти 4 байта (судя по всему это 1 пиксель) повторяются на протяжении всего фрэймбуффера. Буду теперь искать как нарисовать всё целиком одной командой.

mors
() автор топика
Ответ на: комментарий от mors

Добавив

int rect[4] = {0, 0, 16, 16};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
удалось нарисовать и считать буфер целиком!

Получается что я использовал расширение OES_draw_texture из OpenGL ES.

Следующим шагом будет применение шейдера на буфер...

Спасибо за помощь!

mors
() автор топика

1. чтобы подчитать значение пикселя при помощи glReadPixels() нужно отрендерить два полигона (в OGL 2.1 можно рендерить quad), натянув на них текстуру.

2. после семплинга текстуры во фрагментном шейдере (ололо ниатсрелюю как у вас там в OGL 2.1 это бадяжится), растеризации и viewport трансформации рисунок будет отличаться.

x0r ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.