Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Dilim от Ноябрь 06, 2014, 15:39



Название: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 06, 2014, 15:39
Здравствуйте! Столкнулся я с такой проблемой: создаю QGLWidget, определяю функцию initializeGL()
Код:
void GLWidget::initializeGL()
{
glClearColor(0.0, 0.0, 0.0, 1.0);
    glDisable(GL_DEPTH_TEST);

    // viewport
    glViewport(0, 0, window_width, window_height);

    // projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

initglew();

createVBO(&vboPos, &cuda_vbo_resource_pos,2);
createVBO(&vboColor, &cuda_vbo_resource_color,2);
runCudaPos(&cuda_vbo_resource_pos);
runCudaColor(&cuda_vbo_resource_color);
}
функции createVBO и runCuda.... выдраны из примера по совместимости opengl и cuda, который идёт вместе с cuda toolkit. В них создается буфер vbo и связывается с ресурсом cuda.
Код:
void runCudaColor(struct cudaGraphicsResource **vbo_resource)
{
float4 *dptr;
    checkCudaErrors(cudaGraphicsMapResources(1, vbo_resource, 0));
    size_t num_bytes;
    checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void **)&dptr, &num_bytes,
                                                         *vbo_resource));
   
    launch_kernel_color(dptr, dmesh_width, dmesh_height, g_fAnim);

    // unmap buffer object
    checkCudaErrors(cudaGraphicsUnmapResources(1, vbo_resource, 0));
}


Функцию paintGL() определяю следующим образом:
Код:
void display(GLuint *vboPos, GLuint *vboColor)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

     // set view matrix
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
   

     // render from the vbo
glEnableClientState  ( GL_VERTEX_ARRAY );
    glBindBuffer(GL_ARRAY_BUFFER, *vboPos);
    glVertexPointer(4, GL_FLOAT, 0, 0);

glEnableClientState  ( GL_COLOR_ARRAY );
glBindBuffer(GL_ARRAY_BUFFER, *vboColor);
glColorPointer(4, GL_FLOAT, 0, 0);

//glColor3f(1.0, 0.0, 0.0);
     glDrawArrays(GL_POINTS, 0, dmesh_width * dmesh_height);
     glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

   
}
void GLWidget::paintGL()
{
display(&vboPos, &vboColor);
swapBuffers();

}

Проблема заключается в том, что функцию runCudaColor получается вызвать только один раз, если QGLWidget имеет параметр SampleBuffer и только два раза, если QGLWidget имеет DoubleBuffer. Падает функция на строчке checkCudaErrors(cudaGraphicsMapResources(1, vbo_resource, 0)); т.е. при попытке обращения к ресурсу. Такое ощущение, что при вызове paintGL ресурс cuda_vbo_resource_color занимается и больше никогда не освобождается. Подскажите пожалуйста как освободить ресурс после отрисовки?


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 07, 2014, 15:00
дело похоже не в занятости ресурса, а в контесте OGL. Функция cudaGraphicsMapResources возвращает cudaErrorInvalidGraphicsContext после второго вызова. Получается сначала всё хорошо, но потом paintGL() каким то образом портит контекст? Или я что то не так понимаю?


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 07, 2014, 15:05
дело похоже не в занятости ресурса, а в контесте OGL. Функция cudaGraphicsMapResources возвращает cudaErrorInvalidGraphicsContext после второго вызова. Получается сначала всё хорошо, но потом paintGL() каким то образом портит контекст? Или я что то не так понимаю?

swapBuffers точно нужен?
попробуй добавить вызов makeCurrent(), если проблема в контексте.


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 07, 2014, 15:06
если можешь, закинь весь проект. так не совсем понятно.


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 07, 2014, 15:35
swapBuffers точно нужен?
попробуй добавить вызов makeCurrent(), если проблема в контексте.

swapBuffers нужен, когда буфер двойной..
целиком проект слишком большой, в архиве только часть файлов


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 10, 2014, 08:50
swapBuffers точно нужен?
попробуй добавить вызов makeCurrent(), если проблема в контексте.

swapBuffers нужен, когда буфер двойной..
целиком проект слишком большой, в архиве только часть файлов


qglwidget автоматом свапает буферы после paintGL(). ручками нужно вызывать только если 2 потока работают с буфером.
тогда нужно makeCurrent() и doneCurrent() вызывать ещё.

поэтому и просил весь проект, если возможно. так не понятно...

ещё стоит добавить после glDrawArrays
glBindBuffer(GL_ARRAY_BUFFER, 0);

Ну и glBindBuffer(GL_ARRAY_BUFFER, *vboPos); насколько мне известно в качестве второго аргумента ждет индекс буфера, а не указатель на него.


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 12, 2014, 14:43
qglwidget автоматом свапает буферы после paintGL(). ручками нужно вызывать только если 2 потока работают с буфером.
тогда нужно makeCurrent() и doneCurrent() вызывать ещё.

поэтому и просил весь проект, если возможно. так не понятно...

ещё стоит добавить после glDrawArrays
glBindBuffer(GL_ARRAY_BUFFER, 0);

Ну и glBindBuffer(GL_ARRAY_BUFFER, *vboPos); насколько мне известно в качестве второго аргумента ждет индекс буфера, а не указатель на него.

не, проблема не в этом. я создал ещё один проект, там всё прекрасно работает. разница в том, что не рабочий получает данные на отрисовку через winpcap, а рабочий генерит данные сам, причем интерфейс для получения данных один и тот же, я уже не знаю куда копать..


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 12, 2014, 15:00
qglwidget автоматом свапает буферы после paintGL(). ручками нужно вызывать только если 2 потока работают с буфером.
тогда нужно makeCurrent() и doneCurrent() вызывать ещё.

поэтому и просил весь проект, если возможно. так не понятно...

ещё стоит добавить после glDrawArrays
glBindBuffer(GL_ARRAY_BUFFER, 0);

Ну и glBindBuffer(GL_ARRAY_BUFFER, *vboPos); насколько мне известно в качестве второго аргумента ждет индекс буфера, а не указатель на него.

не, проблема не в этом. я создал ещё один проект, там всё прекрасно работает. разница в том, что не рабочий получает данные на отрисовку через winpcap, а рабочий генерит данные сам, причем интерфейс для получения данных один и тот же, я уже не знаю куда копать..

это не очень проект, я такое врядли смогу запустить...))

checkCudaErrors(cudaGraphicsMapResources(1, vbo_resource, 0));
падает с какой ошибкой?

checkCudaErrors отрабатывает? в смысле выдает что-то в консоль об ошибки, или при выполнении вылетает?

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

стэк сюда скопипасти при крэше.


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 12, 2014, 15:07
это не очень проект, я такое врядли смогу запустить...))

checkCudaErrors(cudaGraphicsMapResources(1, vbo_resource, 0));
падает с какой ошибкой?

checkCudaErrors отрабатывает? в смысле выдает что-то в консоль об ошибки, или при выполнении вылетает?

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

стэк сюда скопипасти при крэше.
падает с такой ошибкой: CUDA error code=79(cudaErrorInvalidGraphicsContext)  причем только после третьего вызова, первые два отрабатывает нормально: CUDA error code=0(cudaSuccess) 
а как, прости за тупой вопрос, стэк скопировать?


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 12, 2014, 15:27
это не очень проект, я такое врядли смогу запустить...))

checkCudaErrors(cudaGraphicsMapResources(1, vbo_resource, 0));
падает с какой ошибкой?

checkCudaErrors отрабатывает? в смысле выдает что-то в консоль об ошибки, или при выполнении вылетает?

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

стэк сюда скопипасти при крэше.
падает с такой ошибкой: CUDA error code=79(cudaErrorInvalidGraphicsContext)  причем только после третьего вызова, первые два отрабатывает нормально: CUDA error code=0(cudaSuccess) 
а как, прости за тупой вопрос, стэк скопировать?

в creator'е можно правой кнопкой тыркнуть на стеке и нажать копировать.
print screen работает всегда.

стек отображает ессесно тока в дебаге (ну и вруби window->views->stack, если его не видно).
ну и это только если приложение крэшится, а не просто печатается куда ошибка в консоль.

я верно понимаю, что ты из pcap файла сам парсишь данные? возможно они кривые? возможно данные вообще кривые, которые ты в vbo подгружаешь, отсюда и ошибка...

третий вызов у тебя когда ты пытаешься новый буфер замапить. тут имхо либо буфер кривой, либо нужно делать шаманство с кудой. т.е. нужно контекст может сделать активным или что-то такое... я не очень знаком с кудой, но opengl работает именно так.

посмотри на дебаге что лежит внутри vbo_resource когда ошибка выскакивает.


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 13, 2014, 14:40
о как! оказалось всё дело в потоках! я создаю объект QThread и из него передаю данные в основной поток на отрисовку. так вот в неработающем случае я передаю данные из функции run и эти данные почему не нравятся функции cudaGraphicsMapResources в основном потоке. надо дальше копать..


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 13, 2014, 15:04
о как! оказалось всё дело в потоках! я создаю объект QThread и из него передаю данные в основной поток на отрисовку. так вот в неработающем случае я передаю данные из функции run и эти данные почему не нравятся функции cudaGraphicsMapResources в основном потоке. надо дальше копать..

а как передаешь данные?


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 14, 2014, 11:19
а как передаешь данные?

когда формирование выборки заканчивается посылаю сигнал с указателем на начало выборки, а в слоте беру данные по этому указателю и копирую в память видяхи.


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 14, 2014, 11:23
а как передаешь данные?

когда формирование выборки заканчивается посылаю сигнал с указателем на начало выборки, а в слоте беру данные по этому указателю и копирую в память видяхи.

с каких пор в сигнале можно указатель передавать?

ты бы проверил что там вообще приходит...

сигнал queued?

может лучше скопировать в память видяхи в том же потоке где формируется выборка, а передавать просто ID буфера?
тут главное не забыть сделать gl context основным из потока.
если не ошибаюсь, vbo жестко привязаны к контексту.


Название: Re: OpenGL+Cuda
Отправлено: gil9red от Ноябрь 14, 2014, 11:45
а как передаешь данные?

когда формирование выборки заканчивается посылаю сигнал с указателем на начало выборки, а в слоте беру данные по этому указателю и копирую в память видяхи.

с каких пор в сигнале можно указатель передавать?


С давних :)
Пример из доки: http://qt-project.org/doc/qt-4.8/qactiongroup.html#hovered


Название: Re: OpenGL+Cuda
Отправлено: vulko от Ноябрь 14, 2014, 12:54
а как передаешь данные?

когда формирование выборки заканчивается посылаю сигнал с указателем на начало выборки, а в слоте беру данные по этому указателю и копирую в память видяхи.

с каких пор в сигнале можно указатель передавать?


С давних :)
Пример из доки: http://qt-project.org/doc/qt-4.8/qactiongroup.html#hovered

не совсем то.

так то можно и внутри qobject'а ссылку хранить и передавать.
но автор не уточнил как он передает.


Название: Re: OpenGL+Cuda
Отправлено: Dilim от Ноябрь 17, 2014, 11:22
с каких пор в сигнале можно указатель передавать?

ты бы проверил что там вообще приходит...

сигнал queued?

может лучше скопировать в память видяхи в том же потоке где формируется выборка, а передавать просто ID буфера?
тут главное не забыть сделать gl context основным из потока.
если не ошибаюсь, vbo жестко привязаны к контексту.
да, указатель можно передавать, тут всё норм, данные доходят. проблема была в том, что в параметрах connect`а я указал DirectConnection, а это означало, что слот, соответствующий сигналу из другого потока и выполнялся в том потоке, где был вызван сигнал, а контекст был установлен в основном потоке, соответственно когда дело доходило до функции cudaGraphicsMapResources случался аяяй) Спасибо за подсказки!