[英]calculate a picture with cuda and display it directly with OpenGL
我想編寫一個程序,該程序可以為我計算圖片(實際上是空間光調制器(SLM)的全息圖)。 這應該實時發生。 圖片應在GPU上計算,然后從那里直接顯示在屏幕上(800x600像素)。 我想使用cuda和OpenGL 。 我自己編寫了一個小程序,這只是一個在屏幕上顯示棋盤的示例。 它不起作用,因為我不知道如何將圖片從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;
}
這是正確的方法嗎? 還是我必須使用幀緩沖區。 我其實不想。 我想讓它盡可能簡單。 我必須進行哪些更改才能使其正常工作?
我認為您可以查看DRM / DRI或Linux平面幀緩沖區。 您可以參考DirectFB項目http://www.webos-internals.org/wiki/Directfb 。您將需要使用fbDev0模塊,並可能需要使用該模塊重新編譯內核。 我假設您正在使用linux。
因此,您要在此處執行的操作是繞過整個API層,而直接嘗試操縱幀緩沖區。 DRM是內核中的模塊,用於管理對GPU資源的訪問,因此您可以使用它。
在Windows上,您可以編寫直接寫入frambuffer的微型過濾器驅動程序,也可以使用類似http://www.blackhat.com/presentations/win-usa-04/bh-win-04-butler.pdf的驅動程序。 這是直接內核對象操縱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.