# HG changeset patch # User John Tsiombikas # Date 1282937995 -3600 # Node ID 057b8575a1c1db3368c78e8a0c9377e4ddab202f # Parent 1bcbb53b3505ecb6f65e11d47495684c69d0632c - changed the membuffer into an imagebuffer for the non-GL/CL-interop case - fixed the segfault diff -r 1bcbb53b3505 -r 057b8575a1c1 src/clray.cc --- a/src/clray.cc Fri Aug 27 19:00:14 2010 +0100 +++ b/src/clray.cc Fri Aug 27 20:39:55 2010 +0100 @@ -135,13 +135,14 @@ void cleanup() { - printf("destroying renderer...\n"); + printf("destroying renderer ...\n"); destroy_renderer(); - printf("shutting down OpenCL...\n"); + printf("shutting down OpenCL ...\n"); destroy_opencl(); - printf("done cleaning up\n"); + printf("cleaning up OpenGL resources ...\n"); + glDeleteTextures(1, &tex); } static Matrix4x4 mat, inv_mat, inv_trans; diff -r 1bcbb53b3505 -r 057b8575a1c1 src/ocl.cc --- a/src/ocl.cc Fri Aug 27 19:00:14 2010 +0100 +++ b/src/ocl.cc Fri Aug 27 20:39:55 2010 +0100 @@ -122,17 +122,63 @@ } CLMemBuffer *mbuf = new CLMemBuffer; + mbuf->type = MEM_BUFFER; mbuf->mem = mem; mbuf->size = sz; + mbuf->xsz = mbuf->ysz = 0; mbuf->ptr = 0; mbuf->tex = 0; return mbuf; } -CLMemBuffer *create_mem_buffer(int rdwr, unsigned int tex) +CLMemBuffer *create_image_buffer(int rdwr, int xsz, int ysz, const void *pixels) { - int err; + int err, pitch; cl_mem mem; + cl_mem_flags flags = rdwr | CL_MEM_ALLOC_HOST_PTR; + + if(pixels) { + flags |= CL_MEM_COPY_HOST_PTR; + pitch = xsz * 4 * sizeof(float); + } else { + pitch = 0; + } + + cl_image_format fmt = {CL_RGBA, CL_FLOAT}; + + if(!(mem = clCreateImage2D(ctx, flags, &fmt, xsz, ysz, pitch, (void*)pixels, &err))) { + fprintf(stderr, "failed to create %dx%d image: %s\n", xsz, ysz, clstrerror(err)); + return 0; + } + + CLMemBuffer *mbuf = new CLMemBuffer; + mbuf->type = IMAGE_BUFFER; + mbuf->mem = mem; + mbuf->size = ysz * pitch; + mbuf->xsz = xsz; + mbuf->ysz = ysz; + mbuf->ptr = 0; + mbuf->tex = 0; + return mbuf; +} + +CLMemBuffer *create_image_buffer(int rdwr, unsigned int tex) +{ + int err, xsz, ysz; + cl_mem mem; + + glGetError(); // clear previous OpenGL errors + + glPushAttrib(GL_TEXTURE_BIT); + glBindTexture(GL_TEXTURE_2D, tex); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &xsz); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &ysz); + glPopAttrib(); + + if(glGetError()) { + fprintf(stderr, "create_image_buffer: GL error while retreiving texture parameters for texture %u\n", tex); + return 0; + } if(!(mem = clCreateFromGLTexture2D(ctx, rdwr, GL_TEXTURE_2D, 0, tex, &err))) { fprintf(stderr, "failed to create memory buffer from GL texture %u: %s\n", tex, clstrerror(err)); @@ -140,10 +186,14 @@ } CLMemBuffer *mbuf = new CLMemBuffer; + mbuf->type = IMAGE_BUFFER; mbuf->mem = mem; mbuf->size = 0; + mbuf->xsz = xsz; + mbuf->ysz = ysz; mbuf->ptr = 0; mbuf->tex = tex; + return mbuf; } @@ -166,10 +216,27 @@ #endif int err; - mbuf->ptr = clEnqueueMapBuffer(cmdq, mbuf->mem, 1, rdwr, 0, mbuf->size, 0, 0, ev, &err); - if(!mbuf->ptr) { - fprintf(stderr, "failed to map buffer: %s\n", clstrerror(err)); - return 0; + + if(mbuf->type == MEM_BUFFER) { + mbuf->ptr = clEnqueueMapBuffer(cmdq, mbuf->mem, 1, rdwr, 0, mbuf->size, 0, 0, ev, &err); + if(!mbuf->ptr) { + fprintf(stderr, "failed to map buffer: %s\n", clstrerror(err)); + return 0; + } + } else { + assert(mbuf->type == IMAGE_BUFFER); + + size_t orig[] = {0, 0, 0}; + size_t rgn[] = {mbuf->xsz, mbuf->ysz, 1}; + size_t pitch; + + mbuf->ptr = clEnqueueMapImage(cmdq, mbuf->mem, 1, rdwr, orig, rgn, &pitch, 0, 0, 0, ev, &err); + if(!mbuf->ptr) { + fprintf(stderr, "failed to map image: %s\n", clstrerror(err)); + return 0; + } + + assert(pitch == mbuf->xsz * 4 * sizeof(float)); } return mbuf->ptr; } @@ -177,6 +244,7 @@ void unmap_mem_buffer(CLMemBuffer *mbuf, cl_event *ev) { if(!mbuf || !mbuf->ptr) return; + clEnqueueUnmapMemObject(cmdq, mbuf->mem, mbuf->ptr, 0, 0, ev); mbuf->ptr = 0; } @@ -351,12 +419,29 @@ return true; } +bool CLProgram::set_arg_image(int idx, int rdwr, int xsz, int ysz, const void *pix) +{ + printf("create argument %d from %dx%d image\n", idx, xsz, ysz); + CLMemBuffer *buf; + + if(!(buf = create_image_buffer(rdwr, xsz, ysz, pix))) { + return false; + } + + if((int)args.size() <= idx) { + args.resize(idx + 1); + } + args[idx].type = ARGTYPE_MEM_BUF; + args[idx].v.mbuf = buf; + return true; +} + bool CLProgram::set_arg_texture(int idx, int rdwr, unsigned int tex) { printf("create argument %d from texture %u\n", idx, tex); CLMemBuffer *buf; - if(!(buf = create_mem_buffer(rdwr, tex))) { + if(!(buf = create_image_buffer(rdwr, tex))) { return false; } diff -r 1bcbb53b3505 -r 057b8575a1c1 src/ocl.h --- a/src/ocl.h Fri Aug 27 19:00:14 2010 +0100 +++ b/src/ocl.h Fri Aug 27 20:39:55 2010 +0100 @@ -22,9 +22,17 @@ MAP_RDWR = CL_MAP_READ | CL_MAP_WRITE }; +enum { + MEM_BUFFER, + IMAGE_BUFFER +}; + struct CLMemBuffer { + int type; cl_mem mem; + size_t size; + size_t xsz, ysz; void *ptr; unsigned int tex; }; @@ -34,7 +42,10 @@ void destroy_opencl(); CLMemBuffer *create_mem_buffer(int rdwr, size_t sz, const void *buf); -CLMemBuffer *create_mem_buffer(int rdwr, unsigned int tex); + +CLMemBuffer *create_image_buffer(int rdwr, int xsz, int ysz, const void *pixels = 0); +CLMemBuffer *create_image_buffer(int rdwr, unsigned int tex); + void destroy_mem_buffer(CLMemBuffer *mbuf); void *map_mem_buffer(CLMemBuffer *mbuf, int rdwr, cl_event *ev = 0); @@ -87,6 +98,7 @@ bool set_argi(int arg, int val); bool set_argf(int arg, float val); bool set_arg_buffer(int arg, int rdwr, size_t sz, const void *buf = 0); + bool set_arg_image(int arg, int rdwr, int xsz, int ysz, const void *pix = 0); bool set_arg_texture(int arg, int rdwr, unsigned int tex); CLMemBuffer *get_arg_buffer(int arg); int get_num_args() const; diff -r 1bcbb53b3505 -r 057b8575a1c1 src/rt.cc --- a/src/rt.cc Fri Aug 27 19:00:14 2010 +0100 +++ b/src/rt.cc Fri Aug 27 20:39:55 2010 +0100 @@ -94,7 +94,11 @@ // XXX now we can actually destroy the original kdtree and keep only the GPU version /* setup argument buffers */ +#ifdef CLGL_INTEROP prog->set_arg_texture(KARG_FRAMEBUFFER, ARG_WR, tex); +#else + prog->set_arg_image(KARG_FRAMEBUFFER, ARG_WR, xsz, ysz); +#endif prog->set_arg_buffer(KARG_RENDER_INFO, ARG_RD, sizeof rinf, &rinf); prog->set_arg_buffer(KARG_FACES, ARG_RD, rinf.num_faces * sizeof(Face), faces); prog->set_arg_buffer(KARG_MATLIB, ARG_RD, scn->get_num_materials() * sizeof(Material), scn->get_materials());