2016-04-24 3 views
2

Я пытаюсь использовать OpenCL с OpenGL-взаимодействием. для вычисления алгоритма трассировки на графическом процессоре, а затем нарисовать GL-текстуру в квадрат. Работает по назначению на процессоре Intel, но когда я пытаюсь запустить на GTX 970, есть segfault для разблокировки этой текстуры GL. Dunno, если это причина или запущенное ядро. Я позволю коду говорить сам за себя. Я использую оболочку OpenCL C++.Конструкция взаимодействия OpenCL/OpenGL segfault

GL текстуры распределение создание

glGenTextures(1, &texture); 
glBindTexture(GL_TEXTURE_2D, texture); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer); 
glBindTexture(GL_TEXTURE_2D, 0); //Unbind texture 

CL текстуры

m_textureCL = cl::ImageGL(m_context, 
     CL_MEM_READ_WRITE, 
     GL_TEXTURE_2D, 
     0, 
     texture, 
     &errCode); 

RunKernel функция

//----------------------------------------------------------------------------- 
// Lock texture 
//----------------------------------------------------------------------------- 
std::vector<cl::Memory> glObjects; //Create vector of GL objects to lock 
glObjects.push_back(m_textureCL); //Add created CL texture buffer 
glFlush(); //Flush GL queue 

errCode = m_cmdQueue.enqueueAcquireGLObjects(&glObjects, NULL, NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error locking texture" << errCode << std::endl; 
    return errCode; 
} 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
// Run queue 
//----------------------------------------------------------------------------- 
errCode = m_cmdQueue.enqueueNDRangeKernel(
     m_kernel, 
     cl::NullRange, 
     cl::NDRange(height*width), 
     cl::NullRange, 
     NULL, 
     NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error running queue: " << errCode << std::endl; 
    return errCode; 
} 
//--------------------------------------- 


//----------------------------------------------------------------------------- 
// Unlock 
//----------------------------------------------------------------------------- 
errCode = m_cmdQueue.enqueueReleaseGLObjects(&glObjects, NULL, NULL); 
if(errCode != CL_SUCCESS) { 
    std::cerr << "Error unlocking texture: " << errCode << std::endl; 
    return errCode; 
} <<------ Here's where segfault occurs, can't get past this point 

Функция ядра опр.

__kernel void RadianceGPU (
    __write_only image2d_t texture, 
    other_stuff...) 

Запись текстуры в ядре

write_imagef(
     texture, 
     (int2)(x, height-y-1), 
     (float4)(
      clamp(framebuffer[id].x, 0.0f, 1.0f), 
      clamp(framebuffer[id].y, 0.0f, 1.0f), 
      clamp(framebuffer[id].z, 0.0f, 1.0f), 
      1.0f) * 1.0f); 

Интересно, что write_imagef() работает, несмотря на текстуру будучи UNSIGNED_BYTE.

EDIT: Итак, я, наконец, выяснил, что вызвало проблему. При создании свойств CL он устанавливал неправильный дисплей. Я просто вложил туда окно из GLFW, что вызывает проблемы у драйверов Nvidia. Вам нужно использовать glxGetCurrentDisplay или glfwGetX11Display. Это фиксирует segfault.

+0

Какую версию OpenCL вы используете? – Andreas

+0

Nvidia CUDA 1.2 – Nixx

ответ

2

Я не уверен, что это ваша проблема, но я все равно сделаю это.

У вас нет синхронизированного доступа к glObjects портативным способом. Из OpenCL 1.1:

До вызова clEnqueueAcquireGLObjects, приложение должно гарантировать, что любые ожидающие операции GL, которые доступ к объектам, указанным в mem_objects завершена. Это может быть выполнено с помощью путем выдачи и ожидания завершения команды glFinish во всех контекстах GL с ожидающими ссылки на эти объекты. Реализации могут предлагать более эффективные методы синхронизации; для пример на некоторых платформах, вызывающих glFlush, может быть достаточным, или Синхронизация может быть неявной в потоке, или может быть поставщик - конкретные расширения, которые позволяют размещать забор в потоке команд GL и ждать завершения этого ограждения в команда CL очередь. Обратите внимание, что никакие методы синхронизации, отличные от glFinish, не являются , переносимыми между реализациями OpenGL в это время.

В основном glFinish необходим для портативного поведения.

В пункте ниже уже цитировал есть больше информации, которая может быть интересна:

Аналогично, после вызова clEnqueueReleaseGLObjects, приложение несет ответственность за обеспечение того, чтобы все ожидающие операции OpenCL которых доступ к объектам указанные в mem_objects, завершили перед выполнением последующих команд GL, которые ссылаются на эти объекты . Это можно выполнить переносимо, вызвав clWaitForEvents с объектом события, возвращаемым clEnqueueRelease GL Объекты или вызовом clFinish. Как и выше, некоторые реализации могут предложить более эффективные методы.

Вот ссылка на документ цитировала: https://www.khronos.org/registry/cl/specs/opencl-1.1.pdf#nameddest=section-9.8.6

+0

Спасибо за ваш ответ, я дам ему шанс, как только я получу шанс. Другое дело, что меня беспокоит, когда я выделяю текстуру CL, я не могу получить доступ к текстуре GL. Это происходит, когда я использую Nvidia opencl 1.2 и OpenGL 4.5, но при использовании opencl 1.2 от AMD на процессоре Intel/GPU и OpenGL 3.3 нет никаких проблем. – Nixx

+0

@Nixx Сообщение, что в качестве другого кода вопроса и всего. – Andreas