Отображать растровое изображение в текущем окне непосредственно из памяти устройства (видео) - PullRequest
1 голос
/ 29 декабря 2011

Предположим, у меня уже есть растровое изображение (изображение) в памяти устройства (видео) с использованием cudaMalloc() и cudaMemcpy().

Какой самый простой способ отобразить это растровое изображение прямо на экране (текущее окно)?

Я предполагаю, что должна быть альтернатива GDI BitBlt() ... но любой подход (Direct3D, OpenGL или даже GDI) будет в порядке.

Примеры в CUDA SDK (версия OpenGL) используют Texture, который использует буфер (Pixel Buffer Object) для хранения данных, которые зарегистрированы как CUDA-ресурс, который должен отображаться / не отображаться в каждом кадре (вызов glutDisplayFunc()). И все это кажется немного сложным и неуместным.

1 Ответ

1 голос
/ 31 декабря 2011

Хорошо, постараюсь ответить на мой собственный вопрос. Похоже, есть более простой способ отображения растрового изображения через OpenGL. Вместо использования Texture + Pixel Buffer Object мы могли бы использовать cudaGraphicsGLRegisterImage(), который поддерживает формат текстуры GL_RGBA8, начиная с CUDA Toolkit 4.0.

Для простоты в примере нет cutilSafeCall() или проверок на ошибки. Я мало знаком с OpenGL и буду рад выслушать рекомендации.

#include <stdio.h>
#include <string.h>

#include <GL/glew.h>
#include <GL/freeglut.h>

#include <cuda_runtime_api.h>
#include <cuda_gl_interop.h>

/* Handles OpenGL-CUDA exchange. */
cudaGraphicsResource *cuda_texture;

/* Registers (+ resizes) CUDA-Texture (aka Renderbuffer). */
void resizeTexture(int w, int h) {
    static GLuint gl_texture = 0;

    /* Delete old CUDA-Texture. */
    if (gl_texture) {
        cudaGraphicsUnregisterResource(cuda_texture);
        glDeleteTextures(1, &gl_texture);
    } else glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &gl_texture);
    glBindTexture(GL_TEXTURE_2D, gl_texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    cudaGraphicsGLRegisterImage(&cuda_texture, gl_texture, GL_TEXTURE_2D, cudaGraphicsMapFlagsWriteDiscard);
}

void updateMemDevice(cudaArray *memDevice, int w, int h) {
    struct Color {
        unsigned char r, g, b, a;
    } *memHost = new Color[w*h];

    memset(memHost, 128, w*h*4);
    for (int y = 0; y<h; ++y) {
        for (int x = 0; x<w; ++x) {
            Color &c = memHost[y*w + x];
            c.r = c.b = 255 * x/w;
        }
    }
    cudaMemcpyToArray(memDevice, 0, 0, memHost, w*h*4, cudaMemcpyHostToDevice);
    delete [] memHost;
}

void editTexture(int w, int h) {
    cudaGraphicsMapResources(1, &cuda_texture);
    cudaArray* memDevice;
    cudaGraphicsSubResourceGetMappedArray(&memDevice, cuda_texture, 0, 0);
    updateMemDevice(memDevice, w, h);
    cudaGraphicsUnmapResources(1, &cuda_texture);
}


void windowResizeFunc(int w, int h) {
    glViewport(-w, -h, w*2, h*2);
}

void displayFunc() {
    glBegin(GL_QUADS);
    glTexCoord2i(0, 0); glVertex2i(0, 0);
    glTexCoord2i(1, 0); glVertex2i(1, 0);
    glTexCoord2i(1, 1); glVertex2i(1, 1);
    glTexCoord2i(0, 1); glVertex2i(0, 1);
    glEnd();

    glFlush();
}


int main(int argc, char *argv[]) {
    /* Initialize OpenGL context. */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB);
    glutInitWindowSize(400, 300);
    glutCreateWindow("Bitmap in Device Memory");
    glutReshapeFunc(windowResizeFunc);
    glutDisplayFunc(displayFunc);

    glewInit();

    cudaGLSetGLDevice(0);

    int width = 5, height = 5;
    resizeTexture(width, height);
    editTexture(width, height);

    glutMainLoop();
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...