2017-03-02 105 views
0

如何在設備上創建一些數據,然後在主機上發送/讀取?如何從OpenCL中的設備發送/讀取數據?

我試過,但似乎沒有工作。

#include <CL/cl.h> 

#ifndef DEFS_H 
#define DEFS_H 

#define _BLINNPHONG 
//#define _LAMBERT 
//#define _NOSHADING 

#define NSPHERES 4 
#define VIEWPLANE 500 
#define WINDOW VIEWPLANE*2 
#define FOCALDIST 1000 
#define RADIUS 200 

//#define _ANIMATE 

// typedef enum {false=0, true=1} BOOL; 
// typedef enum {down=0, up=1} DIRECTION; 

#define CRED 0 
#define CGREEN 1 
#define CBLUE 2 
#define true 1 
#define false 0 

/* --------------- VECTORS -------------------- */ 

typedef struct Vector3D{ 
    cl_double x; 
    cl_double y; 
    cl_double z; 
    cl_double dummy1; 
} VECTOR3D; 

typedef struct ray { 
    VECTOR3D origin; 
    VECTOR3D direction; 
} RAY; 

/* ------------------- PIXEL ------------------ */ 
typedef struct pixel { 
    RAY ray; 
    cl_double rgb[4]; 
    cl_int i; 
    cl_int j; 
    cl_int dummy1; 
    cl_int dummy2; 
    cl_int dummy3; 
    cl_int dummy4; 
    cl_int dummy5; 
    cl_int dummy6; 
} PIXEL; 

/* ----------------- VIEWPORT ----------------- */ 
typedef struct vp { 
    cl_int xvmin; 
    cl_int yvmin; 
    cl_int xvmax; 
    cl_int yvmax; 
    PIXEL* pPixels; 
} VIEWPORT; 

/* ---------------- SPHERE -------------------- */ 

typedef struct sp_intersection { 
    cl_double lambda_in; 
    cl_double lambda_out; 
    VECTOR3D normal; 
    VECTOR3D point; 
    cl_int valid; 
} SPHERE_INTERSECTION; 

typedef struct sph { 
    VECTOR3D center; 
    cl_double radius; 
    cl_double kd_rgb[3]; 
    cl_double ks_rgb[3]; 
    cl_double ka_rgb[3]; 
    cl_double shininess; 
    cl_int mirror; 
}SPHERE; 


/* ------------------- RAY --------------------- */ 


/* --------------- VECTOR BASIS ---------------- */ 
typedef struct vb { 
    VECTOR3D u; 
    VECTOR3D v; 
    VECTOR3D n; 
} VEC_BASIS; 

#endif 
In kernel: 

typedef struct pixel { 
    RAY ray; 
    double rgb[4]; 
    int i; 
    int j; 
    int dummy1; 
    int dummy2; 
    int dummy3; 
    int dummy4; 
    int dummy5; 
    int dummy6; 
} PIXEL; 

和內核:

typedef struct Vector3D { 
    double x; 
    double y; 
    double z; 
    double dummy1; 
} VECTOR3D; 

typedef struct ray { 
    VECTOR3D origin; 
    VECTOR3D direction; 
} RAY; 

typedef struct pixel { 
    RAY ray; 
    double rgb[4]; 
    int i; 
    int j; 
    int dummy1; 
    int dummy2; 
    int dummy3; 
    int dummy4; 
    int dummy5; 
    int dummy6; 
} PIXEL; 

void vec_sub(VECTOR3D *v1, VECTOR3D *v2, VECTOR3D *v3) { 
    v1->x = v2->x - v3->x; 
    v1->y = v2->y - v3->y; 
    v1->z = v2->z - v3->z; 
} 

void vec_add(VECTOR3D *v1, VECTOR3D *v2, VECTOR3D *v3) { 
    v1->x = v2->x + v3->x; 
    v1->y = v2->y + v3->y; 
    v1->z = v2->z + v3->z; 
} 


void vec_scale(double scale, VECTOR3D *v1, VECTOR3D *v2) { 
    v1->x = scale * v2->x; 
    v1->y = scale * v2->y; 
    v1->z = scale * v2->z; 
} 

double dotproduct(VECTOR3D *v1, VECTOR3D *v2) { 

    return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z; 
} 

void normalize_vector(VECTOR3D *v) { 

    double magnitude; 

    // 1. calculate the magnitude (length): 
    magnitude = sqrt(dotproduct(v, v)); 

    // 2. normalize the vector: 
    v->x = v->x/magnitude; 
    v->y = v->y/magnitude; 
    v->z = v->z/magnitude; 
} 


__kernel void compute_ray(
     write_only global PIXEL *output, 
     VECTOR3D view_point, 
     VECTOR3D camera_frame_n, 
     VECTOR3D camera_frame_u, 
     VECTOR3D camera_frame_v, 
     const int viewport_xvmin, 
     const int viewport_yvmin, 
     const double distance, 
     const int w, const int h 
) 
{ 
    float u, v; 
    VECTOR3D v1, v2, v3, v4, dir; 
    RAY ray; 
    PIXEL pixel; 

    int gi = get_global_id(0); 
    int i = gi/w; 
    int j = gi % w; 

    u = (float)(viewport_xvmin) + (float)(i) + 0.5f; 
    v = (float)(viewport_yvmin) + (float)(j) + 0.5f; 

    vec_scale(-distance, &v1, &camera_frame_n); 
    vec_scale(u, &v2, &camera_frame_u); 
    vec_scale(v, &v3, &camera_frame_v); 

    ray.origin.x = 22; 
    ray.origin.y = 22; 
    ray.origin.z = 22; 

    vec_add(&v4, &v1, &v2); 
    vec_add(&dir, &v4, &v3); 
    normalize_vector(&dir); 

    ray.direction.x = 11; 
    ray.direction.y = 11; 
    ray.direction.z = 11; 

    pixel.ray = ray; 
    pixel.i = 33; 
    pixel.j = 33; 

    output[i*w*j] = pixel; 
} 

我故意設置I,J,起源和方向結構,以固定數量的,所以我可以,如果號碼被設置在主機上看到

#include <stdio.h> 
#include <stdlib.h> 

#include "vectors.h" 
#include "sphere.h" 
#include "shading.h" 
#include "ray.h" 
#include "stdbool.h" 
#include <CL/cl.h> 

#if defined __APPLE__ 
#include <OpenGL/gl.h> 
#include <OpenGL/glu.h> 
#include <GLUT/glut.h> 
#elif defined (WIN32) 
#include <GL/freeglut.h> 
#else 
#include <GL/gl.h> 
#include <GL/glu.h> 
#include <GL/freeglut_std.h> 
#endif 

#include <time.h> 

VECTOR3D light; 
SPHERE sphere[NSPHERES]; 
static PIXEL pixel; 
VIEWPORT viewport; 
VECTOR3D view_point; 
VEC_BASIS camera_frame; 
cl_double focal_distance; 


double color; 
//double kd_red, kd_green, kd_blue; 
//double ks_red, ks_green, ks_blue; 
double red, green, blue; 
double light_intensity, ambi_light_intensity; 
double theta, reflected_theta; 

int bShadow = 0; 

int direction[NSPHERES]; 

int intersection_object = -1; // none 
double current_lambda = 0x7fefffffffffffff; // maximum positive double 
double current_reflected_lambda = 0x7fefffffffffffff; // maximum positive double 

// window identifier: 
static int win; 

void Timer (int obsolete) { 
    glutPostRedisplay(); 
    glutTimerFunc(10, Timer, 0); 
} 

// opencl stuff 
typedef struct cl_struct { 
    cl_platform_id platform_id; 
    cl_device_id device_id; 
    cl_context context; 
    cl_command_queue queue; 
} cl_struct; 

#define MAX_SOURCE_SIZE (0x100000) 

void disp2(void) { 

    int i,j; 
    PIXEL* pCurrentPixel; 
    PIXEL* pPixels; 

    int VPWIDTH = viewport.xvmax - viewport.xvmin; 
    int VPHEIGHT = viewport.yvmax - viewport.yvmin; 

    pPixels = (PIXEL*)(viewport.pPixels); 

    //clear all pixels: 
    glClear(GL_COLOR_BUFFER_BIT); 

    // For all pixels: 
    for (i=0; i<VPWIDTH; i++) { 
     for (j=0; j<VPHEIGHT; j++) { 

      pCurrentPixel = (PIXEL*)(pPixels + VPWIDTH*i + j); 

      //set color for the current pixel: 
      glColor3f(pCurrentPixel->rgb[0] , pCurrentPixel->rgb[1], pCurrentPixel->rgb[2]); 

      // draw pixel 
      glBegin(GL_POINTS); 
      glVertex2i(i, j); 
      glEnd(); 
     } // j 
    } //i 

    //glFlush(); 
    glutSwapBuffers(); 
} 

void init(void) { 

    direction[0] = 1; 
    direction[1] = 0; 
    direction[2] = 1; 

    pixel.i = 0; 
    pixel.j = 0; 

    // set scene: 
    // 1. define viewport 
    viewport.xvmin = -VIEWPLANE; 
    viewport.yvmin = -VIEWPLANE; 
    viewport.xvmax = VIEWPLANE; 
    viewport.yvmax = VIEWPLANE; 

    // 2. allocate enough space for pixels in viewport 
    viewport.pPixels = (PIXEL *) malloc(sizeof(PIXEL) * (viewport.xvmax - viewport.xvmin) * (viewport.yvmax- viewport.yvmin)); 

    // 3. set camera: 
    camera_frame.u.x = 1.0; 
    camera_frame.u.y = 0.0; 
    camera_frame.u.z = 0.0; 

    camera_frame.v.x = 0.0; 
    camera_frame.v.y = 1.0; 
    camera_frame.v.z = 0.0; 

    camera_frame.n.x = 0.0; 
    camera_frame.n.y = 0.0; 
    camera_frame.n.z = 1.0; 

    view_point.x = (viewport.xvmax - viewport.xvmin)/2.0 ; 
    view_point.y = (viewport.yvmax - viewport.yvmin)/2.0 ; 
    view_point.z = 0.0; 

    // 4. set light: 
    light.x = view_point.x - 1300; 
    light.y = view_point.y + 1300 ; 
    light.z = view_point.z - 300; 


    ambi_light_intensity = 1.0; 
    light_intensity = 1.0; 

    focal_distance = FOCALDIST; 

    // 5. put spheres behind the viewport: 
    sphere[0].radius = RADIUS/1.5; 
    sphere[0].center.x = view_point.x - (RADIUS+30); 
    sphere[0].center.y = view_point.y ; 
    sphere[0].center.z = view_point.z - focal_distance - (2*RADIUS+20); 
    // the first sphere is blue: 
    set_rgb_array(sphere[0].kd_rgb, 0.0, 0.0, 0.8); 
    set_rgb_array(sphere[0].ks_rgb, 1.0, 1.0, 1.0); 
    set_rgb_array(sphere[0].ka_rgb, 0.0, 0.0, 0.2); 
    sphere[0].shininess = 100.0; 
    sphere[0].mirror = false; 

    sphere[1].radius = RADIUS/1.2; 
    sphere[1].center.x = view_point.x + 0; 
    sphere[1].center.y = view_point.y + 50; 
    sphere[1].center.z = view_point.z - focal_distance - (3*RADIUS+20); 
    // the second sphere is green: 
    set_rgb_array(sphere[1].kd_rgb, 0.0, 0.5, 0.0); 
    set_rgb_array(sphere[1].ks_rgb, 1.0, 1.0, 1.0); 
    set_rgb_array(sphere[1].ka_rgb, 0.0, 0.2, 0.0); 
    sphere[1].shininess = 10.0; 
    sphere[1].mirror = false; 


    sphere[2].radius = RADIUS; 
    sphere[2].center.x = view_point.x + (2*RADIUS+30); 
    sphere[2].center.y = view_point.y + 100; 
    sphere[2].center.z = view_point.z - focal_distance - (4*RADIUS+20); 
    // the third sphere is red: 
    set_rgb_array(sphere[2].kd_rgb, 1.0, 0.0, 0.0); 
    set_rgb_array(sphere[2].ks_rgb, 1.0, 1.0, 1.0); 
    set_rgb_array(sphere[2].ka_rgb, 0.2, 0.0, 0.0); 
    sphere[2].shininess = 100.0; 
    sphere[2].mirror = false; 


    sphere[3].radius = 1*RADIUS; 
    sphere[3].center.x = view_point.x ; 
    sphere[3].center.y = view_point.y - 100*RADIUS-130; 
    sphere[3].center.z = view_point.z - focal_distance - (4*RADIUS+20); 
    // the third sphere is red: 
    set_rgb_array(sphere[3].kd_rgb, 0.5, 0.5, 0.5); 
    set_rgb_array(sphere[3].ks_rgb, 1.0, 1.0, 1.0); 
    set_rgb_array(sphere[3].ka_rgb, 0.5, 0.5, 0.5); 
    sphere[3].shininess = 100.0; 
    sphere[3].mirror = false; 

    // set clearing (background) color to white: 
    glClearColor(0.0, 0.0, 0.0, 0.0); 
    // specify that ortgogonal 2D projection is to be used to 
    // map context of 2D world coordinats to the screen. We use the 
    // world-coordinate rectangle of the same aspect ratio as the display window 
    // so ther is no distortion: 
    glMatrixMode(GL_PROJECTION); 
    gluOrtho2D(0.0, WINDOW, 0.0, WINDOW); 
} 

int main(int argc, const char * argv[]) { 
    clock_t startCPU, endCPU, startGPU, endGPU; 

    // init glut: 
    glutInit (&argc, argv); 
    // specify the display mode to be RGB and single buffering: 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); 
    // specify the initial window position: 
    glutInitWindowPosition(100, 100); 
    // specify the initial window size: 
    glutInitWindowSize(WINDOW,WINDOW); 
    // create the window and set title: 
    win = glutCreateWindow("Basic Ray Tracer by Pa3cio, UL FRI"); 

    init(); 

    // Create the two input vectors 
    int i, j, k, l; 

    int VPWIDTH = viewport.xvmax - viewport.xvmin; 
    int VPHEIGHT = viewport.yvmax - viewport.yvmin; 

    // PIXEL* pixels = (PIXEL*) malloc(sizeof(PIXEL) * VPWIDTH * VPHEIGHT); 
    PIXEL* pPixelsFromGPU = (PIXEL*) malloc(sizeof(PIXEL) * VPWIDTH * VPHEIGHT); 

    PIXEL* pCurrentPixel; 
    PIXEL* pPixels; 
    RAY ray, shadow_ray; 

    SPHERE_INTERSECTION intersection, current_intersection, shadow_ray_intersection; 

    // Load the kernel source code into the array source_str 
    FILE *fp; 
    char *source_str; 
    size_t source_size; 

    fp = fopen("/home/rokj/sula/vpsa/seminarska/kernel.cl", "r"); 
    if (!fp) { 
     fprintf(stderr, "Failed to load kernel.\n"); 
     exit(1); 
    } 
    source_str = (char*)malloc(MAX_SOURCE_SIZE); 
    source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp); 
    fclose(fp); 

    // Get platform and device information 
    cl_platform_id platform_id = NULL; 
    cl_device_id device_id = NULL; 
    cl_uint ret_num_devices; 
    cl_uint ret_num_platforms; 
    cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms); 
    ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, 
          &device_id, &ret_num_devices); 

    // Create an OpenCL context 
    cl_context context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret); 

    // Create a command queue 
    cl_command_queue command_queue = clCreateCommandQueue(context, device_id, 0, &ret); 

    // Create memory buffers on the device for each vector 
    cl_mem output = clCreateBuffer(context, CL_MEM_WRITE_ONLY|CL_MEM_ALLOC_HOST_PTR, 
             VPWIDTH * VPHEIGHT * sizeof(PIXEL), NULL, &ret); 

    // Create a program from the kernel source 
    cl_program program = clCreateProgramWithSource(context, 1, 
                (const char **)&source_str, (const size_t *)&source_size, &ret); 

    // Build the program 
    ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); 

    // Create the OpenCL kernel 
    cl_kernel kernel = clCreateKernel(program, "compute_ray", &ret); 

    // Set the arguments of the kernel 
    ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&output); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 1\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 1, sizeof(VECTOR3D), &view_point); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 2\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 2, sizeof(VECTOR3D), &camera_frame.n); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 3\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 3, sizeof(VECTOR3D), &camera_frame.u); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 4\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 4, sizeof(VECTOR3D), &camera_frame.v); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 5\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 5, sizeof(cl_int), &viewport.xvmin); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 6\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 6, sizeof(cl_int), &viewport.yvmin); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 7\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 7, sizeof(cl_double), &focal_distance); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 7\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 8, sizeof(cl_int), &VPWIDTH); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 9\n", stderr); 
     exit(1); 
    } 

    ret = clSetKernelArg(kernel, 9, sizeof(cl_int), &VPHEIGHT); 
    if (ret != CL_SUCCESS) { 
     fputs("error setting CL kernel arg 10\n", stderr); 
     exit(1); 
    } 

    ret = clFinish(command_queue); 

    // Execute the OpenCL kernel on the list 
    size_t global_item_size = VPWIDTH * VPHEIGHT; // Process the entire lists 
    size_t local_item_size = 1024; // Divide work items into groups of 64 

    ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, 
           &global_item_size, &local_item_size, 0, NULL, NULL); 

    // Read the memory buffer C on the device to the local variable C 
    ret = clEnqueueReadBuffer(command_queue, output, CL_TRUE, 0, 
           VPWIDTH * VPHEIGHT * sizeof(PIXEL), pPixelsFromGPU, 0, NULL, NULL); 

    // Display the result to the screen 
    //for(i = 0; i < LIST_SIZE; i++) 
    // printf("%d + %d = %d\n", A[i], B[i], C[i]); 

    // Clean up 
// ret = clFlush(command_queue); 
// ret = clFinish(command_queue); 
// ret = clReleaseKernel(kernel); 
// ret = clReleaseProgram(program); 
// ret = clReleaseMemObject(b_mem_obj); 
// ret = clReleaseCommandQueue(command_queue); 
// ret = clReleaseContext(context); 


    pPixels = (PIXEL*) (pPixelsFromGPU); 

    // For all pixels: 
    for (i=0; i<VPWIDTH; i++) { 
     for (j=0; j<VPHEIGHT; j++) {  
      //pCurrentPixel = (PIXEL*)(pPixels + VPWIDTH*i + j); 
      // here I try to get pixel set on GPU, but it does not work 
      pCurrentPixel = &pPixels[i*VPWIDTH+j]; 

     } //j 
    } //i 

    viewport.pPixels = (PIXEL*) (pPixelsFromGPU); 

    // register callback function to display graphics: 
    glutDisplayFunc(disp2); 
    // call Timer(): 
    Timer(0); 
    // enter tha main loop and process events: 
    glutMainLoop(); 

    free(pPixelsFromGPU); 

    return 0; 
} 

定義。

然後我試圖獲得像素上GPU設置在線路

pCurrentPixel = & pPixels [I * VPWIDTH + D];

但pCurrentPixel->我例如是0而不是33

代碼與下列命令編譯:

gcc -c main.c -o main.o 
gcc -c shading.c -o shading.o 
gcc -c sphere.c -o sphere.o 
gcc -c ray.c -o ray.o 
gcc -c vectors.c -o vectors.o 
gcc -I/usr/include -L/usr/lib/x86_64-linux-gnu main.o shading.o sphere.o ray.o vectors.o -lGL -lglut -lGLU -lX11 -lm -lrt -lOpenCL -o main 
+0

如果它是您編寫的結構數組,它可能是未定義的行爲。例如,像素可能與主機中的設備尺寸不同,可能需要不同的對齊。 –

+0

你需要提供一個合適的[mcve]。在你提供的代碼中,'輸出[i * w * j]'的含義並不清楚。 'i','w'和'j'是否是索引?這些值是如何派生的?像素是如何計算的?最重要的是,代碼中的哪些地方將'output'分配給了內核的參數?這裏提供的信息不足以診斷您的問題。 – Xirema

+0

添加了其他信息。 –

回答

0

除了設置右VPWIDTH和VPHEIGHT output[i*w*j] = pixel;不得不被改變爲output[i*w+j] = pixel;在C代碼中。

相關問題