如何在OpenCL中从设备发送/读取数据?

时间:2017-03-02 19:02:47

标签: opencl

如何在设备上创建一些数据然后在主机上发送/读取?

我试过以下但似乎没有用。

[incomingsipgate]
exten => 0000000,1,Goto(sipgate-in-premium,0000000,1)

[sipgate-in-premium]
exten => 0000000,1,Verbose(Incoming call from Sipgate line CallerID=${CALLERID(all)})
exten => 0000000,2,Goto(internal-ext,120,1)

[internal-ext]
exten => 120,1,Dial(SCCP/120,20,o,CallerID=${CALLERID(all)})

主持人的定义:

exten => _90500.,1,Dial(PJSIP/${EXTEN:1}@sipgate-preimum)

内核:

#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;
}

我故意将i,j,原点和方向结构设置为固定数字,这样我就可以看到是否设置了数字。

然后我尝试在线上

获取GPU上的像素集
  

pCurrentPixel =&amp; pPixels [i * VPWIDTH + j];

但是pCurrentPixel-&gt; i例如是0而不是33。

代码使用以下命令编译:

#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;

1 个答案:

答案 0 :(得分:0)

除了设置正确的VPWIDTH和VPHEIGHT output[i*w*j] = pixel;必须在C代码中更改为output[i*w+j] = pixel;