Подтвердить что ты не робот

Cuda и OpenGL Interop

Я читал документацию CUDA, и мне кажется, что каждый буфер, который должен взаимодействовать с OpenGL, должен быть создан в glBuffer.

В соответствии с руководством по программированию nvidia это должно быть выполнено следующим образом:

GLuint positionsVBO;
struct cudaGraphicsResource* positionsVBO_CUDA;

int main() {

    // Explicitly set device
    cudaGLSetGLDevice(0);
    // Initialize OpenGL and GLUT
    ...
    glutDisplayFunc(display);
    // Create buffer object and register it with CUDA
    glGenBuffers(1, positionsVBO);
    glBindBuffer(GL_ARRAY_BUFFER, &vbo);
    unsigned int size = width * height * 4 * sizeof(float);
    glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    cudaGraphicsGLRegisterBuffer(&positionsVBO_CUDA, positionsVBO, cudaGraphicsMapFlagsWriteDiscard);

    // Launch rendering loop
    glutMainLoop();
}
void display() {
    // Map buffer object for writing from CUDA
    float4* positions;
    cudaGraphicsMapResources(1, &positionsVBO_CUDA, 0);
    size_t num_bytes;
    cudaGraphicsResourceGetMappedPointer((void**)&positions, &num_bytes, positionsVBO_CUDA));
    // Execute kernel
    dim3 dimBlock(16, 16, 1);
    dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1);
    createVertices<<<dimGrid, dimBlock>>>(positions, time, width, height);
    // Unmap buffer object
    cudaGraphicsUnmapResources(1, &positionsVBO_CUDA, 0);
    // Render from buffer object
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBindBuffer(GL_ARRAY_BUFFER, positionsVBO);
    glVertexPointer(4, GL_FLOAT, 0, 0);
    glEnableClientState(GL_VERTEX_ARRAY);
    glDrawArrays(GL_POINTS, 0, width * height);
    glDisableClientState(GL_VERTEX_ARRAY);
    // Swap buffers
    glutSwapBuffers();
    glutPostRedisplay();
}
void deleteVBO() {
    cudaGraphicsUnregisterResource(positionsVBO_CUDA);
    glDeleteBuffers(1, &positionsVBO);
}

__global__ void createVertices(float4* positions, float time, unsigned int width, unsigned int height) { 
    // [....]
}

Есть ли способ предоставить cudaMalloc пространство памяти непосредственно в OpenGL? У меня уже есть рабочий код, написанный на cuda, и я хочу разместить свой массив float4 непосредственно в OpenGL.

Скажем, если у вас уже есть код:

float4 *cd = (float4*) cudaMalloc(elements*sizeof(float4)). 
do_something<<<16,1>>>(cd);

И я хотел отобразить вывод do_something через OpenGL.

Боковое примечание: почему функция cudaGraphicsResourceGetMappedPointer работает на каждом временном интервале?

4b9b3361

Ответ 1

Как и в случае CUDA 4.0, взаимодействие OpenGL одностороннее. Это означает сделать то, что вы хотите (запустить ядро ​​CUDA, которое записывает данные в буфер GL или изображение с текстурой), вам нужно сопоставить буфер с указателем устройства и передать этот указатель на свое ядро, как показано в вашем примере.

Как для вашей стороны примечание: cudaGraphicsResourceGetMappedPointer вызывается каждый раз, когда вызывается display(), потому что cudaGraphicsMapResource вызывается каждый кадр. Каждый раз, когда вы перегруппируете ресурс, вы должны повторно отобразить отображаемый указатель, потому что он может быть изменен. Зачем переквалифицировать каждый кадр? Ну, OpenGL иногда перемещает объекты буфера вокруг в памяти по причинам производительности (особенно в приложениях с интенсивным использованием памяти). Если вы оставите ресурс сопоставленным все время, он не сможет этого сделать, и производительность может пострадать. Я считаю, что GL-способность и необходимость виртуализации объектов памяти также является одной из причин того, что текущий GL-interop API является односторонним (GL не разрешает перемещать распределения CUDA, и поэтому вы не можете отображать указатель устройства, назначенный CUDA в объект буфера GL).