He estado leyendo la documentación de CUDA y me parece que cada búfer que necesita para interactuar con OpenGL necesita ser creado en el glBuffer.Cuda y OpenGL Interop
De acuerdo con la guía de programación de Nvidia, esto tiene que ser hecho de esta manera:
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) {
// [....]
}
¿Hay una manera de dar al cudaMalloc creado un espacio de memoria directamente a OpenGL? Ya tengo el código de trabajo escrito en cuda y quiero poner mi matriz float4 directamente en OpenGL.
Di if've ya tiene un código como:
float4 *cd = (float4*) cudaMalloc(elements*sizeof(float4)).
do_something<<<16,1>>>(cd);
y quería mostrar la salida de hacer_algo través de OpenGL.
Nota al margen: ¿por qué la función cudaGraphicsResourceGetMappedPointer se ejecuta en cada paso de tiempo?
así que supongo que no hay forma de evitar esto en este momento. Esperemos una mejor interoperabilidad en el futuro. – Pascal
No veo lo que está mal con eso. Sí, sería más conveniente también poder pasar un puntero de dispositivo a OpenGL para usarlo como textura o VBO, pero no es tan fácil, y no veo por qué el otro camino no funciona solo también. ¿Tiene un caso de uso donde no puede hacer que su kernel escriba directamente en un puntero mapeado? – harrism
Es principalmente un problema de velocidad. Digamos que quiero hacer algo de hpc, entonces quiero estar seguro de que no hay ninguna sobrecarga adicional mientras se usa el búfer de OpenGL. Y sería más fácil programarlo: solo dale a OpenGL la dirección en la tarjeta gráfica y cuéntale cuán grande es. – Pascal