【问题标题】:calculate a picture with cuda and display it directly with OpenGL用cuda计算一张图片,直接用OpenGL显示
【发布时间】:2019-02-21 11:08:27
【问题描述】:

我想编写一个程序来计算我的图片(实际上是空间光调制器 (SLM) 的全息图)。这应该实时发生。图片应在 GPU 上计算,然后直接从那里显示在屏幕上(800x600 像素)。我想使用 cudaOpenGL。我自己写了一个小程序,它只是一个在屏幕上显示棋盘的例子。它不起作用,因为我不知道如何将图片从 cuda 传递到 OpenGL。特别是我不知道图像资源是什么。我如何声明它。如何将计算出来的图片分配给它?

这是我的代码:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include "cuda_gl_interop.h"

/*  Create checkerboard texture  */
#define checkImageWidth 1024
#define checkImageHeight 1024
#define SIZE_X 1024
#define SIZE_Y 1024
static GLubyte checkImage[ 1024 ][ 1024 ][ 1 ];
/*static GLubyte checkImage[1024][1024][1];*/
static GLuint texName;
// Texture reference for 2D float texture
float tex[ 1024 ][ 1024 ];
float dA[ 1024 * 1024 ];
// 2D float texture
texture<float, cudaTextureType2D, cudaReadModeElementType> texRef;
float *d_A;
size_t dsize = 1024 * 1024 * sizeof( float );
struct mystruct
{
    int x;
    int y;
};

void makeCheckImage( void )
{
    int i, j, c;

    for( i = 0; i < 600; i++ )
    {
        for( j = 0; j < 800; j++ )
        {
            c = ( ( ( ( i % 2 ) == 0 ) ) ^ ( j % 2 == 0 ) ) * 255;
            checkImage[ i ][ j ][ 0 ] = (GLubyte)c;
        }
    }
}

__global__ void cudaMakeCheckImage( float *c )
{

    int col = threadIdx.x + blockIdx.x * blockDim.x;
    int row = threadIdx.y + blockIdx.y * blockDim.y;
    int index = col + row * 1024;
    if( col < 1024 && row < 1024 )
    {
        c[ index ] = ( ( ( ( col % 2 ) == 0 ) ) ^ ( row % 2 == 0 ) ) * 255;
    }
}

void init( void )
{
    glClearColor( 0.0, 0.0, 0.0, 0.0 );
    glShadeModel( GL_FLAT );
    glEnable( GL_DEPTH_TEST );

    cudaMakeCheckImage << <1024, 1024 >> > ( d_A );

    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

    //makeCheckImage();
    glGenTextures( 1, &texName );
    glBindTexture( GL_TEXTURE_2D, texName );
    // set basic parameters
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    // Create texture data 
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, checkImageWidth, checkImageHeight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, checkImage );
    // Unbind the texture
    glBindTexture( GL_TEXTURE_2D, 0 );

    cudaMalloc( &d_A, dsize );
    cudaGraphicsResource* Res;

    // Allocate CUDA array in device memory
    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc( 32, 0, 0, 0, cudaChannelFormatKindFloat );

    cudaArray* CuArr;

    cudaMallocArray( &CuArr, &channelDesc, 1024, 1024 );

    cudaError_t eError = cudaGraphicsGLRegisterImage( &Res, texName, GL_TEXTURE_2D, cudaGraphicsMapFlagsWriteDiscard );
    cudaGraphicsMapResources( 1, &Res, 0 );
    cudaMemcpy2DToArray( CuArr, 0, 0, d_A, 1024, 1024, 1024, cudaMemcpyDeviceToDevice );
    cudaGraphicsSubResourceGetMappedArray( &CuArr, Res, 0, 0 );
    cudaGraphicsUnmapResources( 1, &Res, 0 );
}

void display( void )
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glEnable( GL_TEXTURE_2D );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
    glBindTexture( GL_TEXTURE_2D, texName ); /* binds texname wit active textureunit   */
    glBegin( GL_QUADS );
    glTexCoord2f( 1.0 * 800 / 1024, 1.0 * 600 / 1024 );  glVertex2f( 1.0, 1.0 );
    glTexCoord2f( 1.0 * 800 / 1024, 0.0 );  glVertex2f( 1.0, -1.0 );
    glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 );
    glTexCoord2f( 0.0, 1.0 * 600 / 1024 ); glVertex2f( -1.0, 1.0 );

    glEnd();
    glFlush();
    glBindTexture( GL_TEXTURE_2D, 0 ); /*  unbinds texname with active textureunit  ?? */
    glDisable( GL_TEXTURE_2D );
}

void keyboard( unsigned char key, int x, int y )
{
    switch( key )
    {
    case 27:
        exit( 0 );
        break;
    default:
        break;
    }
}

int main( int argc, char** argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH | GLUT_BORDERLESS | GLUT_CAPTIONLESS );
    glutInitWindowSize( 800, 600 );
    glutInitWindowPosition( 100, 100 );
    glutCreateWindow( argv[ 0 ] );
    cudaSetDevice( 0 );
    cudaGLSetGLDevice( 0 );
    init();

    glutDisplayFunc( display );

    glutKeyboardFunc( keyboard );

    glutMainLoop();
    return 0;
}

这是正确的做法吗?还是我必须使用帧缓冲区。我其实不想。我想让它尽可能简单。我必须进行哪些更改才能使其正常工作?

【问题讨论】:

标签: c++ opengl cuda glut


【解决方案1】:

我认为您可以查看 DRM/DRI 或 Linux 平面帧缓冲区。您可以参考 DirectFB 项目http://www.webos-internals.org/wiki/Directfb。您将需要 fbDev0 模块,并且可能需要使用该模块重新编译您的内核。我假设您使用的是linux。

因此,您在这里尝试做的是绕过整个 API 层并直接尝试操作帧缓冲区。 DRM 是内核中的模块,用于管理对 GPU 资源的访问,因此您可以使用它。

在 Windows 上,您可以编写直接写入帧缓冲区的微型过滤器驱动程序,或者您可以使用类似 http://www.blackhat.com/presentations/win-usa-04/bh-win-04-butler.pdf 的东西。这是直接内核对象操作。

【讨论】:

  • 好的,我认为这对我来说有点高级。目前我只想让它工作。我设法使代码正常工作并将其作为对我的问题的回答,但我只得到了一个黑框而不是黑白图案,如所愿。你能告诉我我做错了什么吗?
  • 我不确定你尝试了什么?您是说您尝试了我的建议但没有立即发布,或者您在原始帖子中发布的代码中当前正在执行的操作没有正确发布?
  • 我试图从我回答的帖子中获得正确的输出。你发给我的链接是我不知道该怎么做的话题。实际上我想要一个工作代码......我想我不必编写驱动程序。必须有一个只有 cuda 和 openGL 的解决方案,你不这么认为吗?
  • 基本上我试图回答您的评论,即您希望它尽快并且不使用 opengl 中的帧缓冲区。我不知道您当前的代码不起作用
猜你喜欢
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
相关资源
最近更新 更多