私はCUDAとOpenGLが初めてだと言って始めたいと思います。上記の実行時エラーが発生しglutMainLoop()
、メインループが実行されglDrawPixels()
ます。なぜこれがうまくいかないのかを理解するために、私はあらゆる場所を見てきました。
#include<stdio.h>
#include<stdlib.h>
#include<gl/glut.h>
#include<stb_image.c>
#include<cuda.h>
#include<cuda_gl_interop.h>
#include<gl/glext.h>
static void HandleError( cudaError_t err, const char *file, int line ) {
if (err != cudaSuccess) {
fprintf(stderr, "%s in %s at line %d\n", cudaGetErrorString( err ), file, line );
system("PAUSE");
//exit( EXIT_FAILURE );
}
}
#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
#define DIM 512
#define GET_PROC_ADDRESS( str ) wglGetProcAddress( str )
PFNGLBINDBUFFERARBPROC glBindBuffer = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers = NULL;
PFNGLGENBUFFERSARBPROC glGenBuffers = NULL;
PFNGLBUFFERDATAARBPROC glBufferData = NULL;
GLuint bufferObj; /* how OpenGL calls the buffer */
cudaGraphicsResource *resource; /* how CUDA calls this same buffer */
uchar4* devPtr; /* friendly pointer to the handles above */
const int size = DIM * DIM;
struct cuComplex
{
float r;
float i;
__device__ cuComplex(float a, float b) : r(a), i(b){ }
__device__ float magnitude2(void)
{
return r * r + i * i;
}
__device__ cuComplex operator *(const cuComplex & a)
{
return cuComplex(r*a.r - i*a.i, i*a.r + r*a.i);
}
__device__ cuComplex operator+(const cuComplex & a)
{
return cuComplex(r+a.r, i+a.i);
}
};
__device__ int julia (int x, int y)
{
const float scale = 1.5;
float jx = scale *(float)(DIM/2 - x)/(DIM/2);
float jy = scale *(float)(DIM/2 - y)/(DIM/2);
cuComplex c(-0.8, 0.156);
cuComplex a(jx,jy);
int i = 0;
for(i=0; i<200; i++)
{
a = a * a + c;
if(a.magnitude2() > 1000)
{
return 0;
}
}
return 1;
}
__global__ void kernel(uchar4 *ptr)
{
int x = blockIdx.x;
int y = blockIdx.y;
int offset = x + y * gridDim.x * blockDim.x;
int juliaValue = julia(x,y);
ptr[offset].x = 255 * juliaValue;
ptr[offset].y = 0;
ptr[offset].z = 0;
ptr[offset].w = 255;
}
static void Draw( void ) {
glDrawPixels( DIM, DIM, GL_RGBA, GL_UNSIGNED_BYTE,0); //ERROR HAPPENS HERE
glutSwapBuffers();
}
void display_and_exit() {
cudaDeviceProp prop;
int dev;
memset( &prop, 0, sizeof( cudaDeviceProp ) );
prop.major = 1;
prop.minor = 0;
HANDLE_ERROR( cudaChooseDevice( &dev, &prop ) );
/*
* Interoperability with OpenGL requires that the CUDA device
* be specified by cudaGLSetGLDevice() before any other runtime calls.
*/
HANDLE_ERROR( cudaGLSetGLDevice( dev ) );
/*
* a bug in the Windows GLUT implementation prevents us from
* passing zero arguments to glutInit()
*/
int c=1;
char* dummy = "";
glutInit( &c, &dummy );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
glutInitWindowSize (DIM, DIM);
glutInitWindowPosition (100, 100);
glutCreateWindow("CUDA and OpenGL example" );
printf("OpenGL version: %s\n", glGetString(GL_VERSION));
dim3 grid(DIM, DIM);
kernel<<<grid,1>>>(devPtr);
glutDisplayFunc(Draw);
/*
* Get pointers to functions (glext.h)
*/
glBindBuffer = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
glGenBuffers = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
glBufferData = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData");
glutMainLoop();
}
int main() {
display_and_exit();
return(0);
}