Clover Git
OpenCL 1.1 software implementation

memobject.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the copyright holder nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00033 #include "memobject.h"
00034 #include "context.h"
00035 #include "deviceinterface.h"
00036 #include "propertylist.h"
00037 
00038 #include <cstdlib>
00039 #include <cstring>
00040 #include <iostream>
00041 
00042 using namespace Coal;
00043 
00044 /*
00045  * MemObject
00046  */
00047 
00048 MemObject::MemObject(Context *ctx, cl_mem_flags flags, void *host_ptr,
00049                      cl_int *errcode_ret)
00050 : Object(Object::T_MemObject, ctx), p_num_devices(0), p_flags(flags),
00051   p_host_ptr(host_ptr), p_devicebuffers(0), p_dtor_callback(0)
00052 {
00053     // Check the flags value
00054     const cl_mem_flags all_flags = CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY |
00055                                    CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR |
00056                                    CL_MEM_ALLOC_HOST_PTR | CL_MEM_COPY_HOST_PTR;
00057 
00058     if ((flags & ~all_flags) != 0)
00059     {
00060         *errcode_ret = CL_INVALID_VALUE;
00061         return;
00062     }
00063 
00064     if ((flags & CL_MEM_ALLOC_HOST_PTR) && (flags & CL_MEM_USE_HOST_PTR))
00065     {
00066         *errcode_ret = CL_INVALID_VALUE;
00067         return;
00068     }
00069 
00070     if ((flags & CL_MEM_COPY_HOST_PTR) && (flags & CL_MEM_USE_HOST_PTR))
00071     {
00072         *errcode_ret = CL_INVALID_VALUE;
00073         return;
00074     }
00075 
00076     // Check other values
00077     if ((flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) != 0 && !host_ptr)
00078     {
00079         *errcode_ret = CL_INVALID_HOST_PTR;
00080         return;
00081     }
00082 
00083     if ((flags & (CL_MEM_USE_HOST_PTR | CL_MEM_COPY_HOST_PTR)) == 0 && host_ptr)
00084     {
00085         *errcode_ret = CL_INVALID_HOST_PTR;
00086         return;
00087     }
00088 }
00089 
00090 MemObject::~MemObject()
00091 {
00092     if (p_dtor_callback)
00093         p_dtor_callback((cl_mem)this, p_dtor_userdata);
00094 
00095     if (p_devicebuffers)
00096     {
00097         // Also delete our children in the device
00098         for (unsigned int i=0; i<p_num_devices; ++i)
00099             delete p_devicebuffers[i];
00100 
00101         std::free((void *)p_devicebuffers);
00102     }
00103 }
00104 
00105 cl_int MemObject::init()
00106 {
00107     // Get the device list of the context
00108     DeviceInterface **devices = 0;
00109     cl_int rs;
00110 
00111     rs = ((Context *)parent())->info(CL_CONTEXT_NUM_DEVICES,
00112                                      sizeof(unsigned int),
00113                                      &p_num_devices, 0);
00114 
00115     if (rs != CL_SUCCESS)
00116         return rs;
00117 
00118     p_devices_to_allocate = p_num_devices;
00119     devices = (DeviceInterface **)std::malloc(p_num_devices *
00120                                         sizeof(DeviceInterface *));
00121 
00122     if (!devices)
00123         return CL_OUT_OF_HOST_MEMORY;
00124 
00125     rs = ((Context *)parent())->info(CL_CONTEXT_DEVICES,
00126                                      p_num_devices * sizeof(DeviceInterface *),
00127                                      devices, 0);
00128 
00129     if (rs != CL_SUCCESS)
00130     {
00131         std::free((void *)devices);
00132         return rs;
00133     }
00134 
00135     // Allocate a table of DeviceBuffers
00136     p_devicebuffers = (DeviceBuffer **)std::malloc(p_num_devices *
00137                                              sizeof(DeviceBuffer *));
00138 
00139     if (!p_devicebuffers)
00140     {
00141         std::free((void *)devices);
00142         return CL_OUT_OF_HOST_MEMORY;
00143     }
00144 
00145     // If we have more than one device, the allocation on the devices is
00146     // defered to first use, so host_ptr can become invalid. So, copy it in
00147     // a RAM location and keep it. Also, set a flag telling CPU devices that
00148     // they don't need to reallocate and re-copy host_ptr
00149     if (p_num_devices > 1 && (p_flags & CL_MEM_COPY_HOST_PTR))
00150     {
00151         void *tmp_hostptr = std::malloc(size());
00152 
00153         if (!tmp_hostptr)
00154         {
00155             std::free((void *)devices);
00156             return CL_OUT_OF_HOST_MEMORY;
00157         }
00158 
00159         std::memcpy(tmp_hostptr, p_host_ptr, size());
00160 
00161         p_host_ptr = tmp_hostptr;
00162         // Now, the client application can safely std::free() its host_ptr
00163     }
00164 
00165     // Create a DeviceBuffer for each device
00166     unsigned int failed_devices = 0;
00167 
00168     for (unsigned int i=0; i<p_num_devices; ++i)
00169     {
00170         DeviceInterface *device = devices[i];
00171 
00172         rs = CL_SUCCESS;
00173         p_devicebuffers[i] = device->createDeviceBuffer(this, &rs);
00174 
00175         if (rs != CL_SUCCESS)
00176         {
00177             p_devicebuffers[i] = 0;
00178             failed_devices++;
00179         }
00180     }
00181 
00182     if (failed_devices == p_num_devices)
00183     {
00184         // Each device found a reason to reject the buffer, so it's invalid
00185         std::free((void *)devices);
00186         return rs;
00187     }
00188 
00189     std::free((void *)devices);
00190     devices = 0;
00191 
00192     // If we have only one device, already allocate the buffer
00193     if (p_num_devices == 1)
00194     {
00195         if (!p_devicebuffers[0]->allocate())
00196             return CL_MEM_OBJECT_ALLOCATION_FAILURE;
00197     }
00198 
00199     return CL_SUCCESS;
00200 }
00201 
00202 bool MemObject::allocate(DeviceInterface *device)
00203 {
00204     DeviceBuffer *buffer = deviceBuffer(device);
00205 
00206     if (!buffer->allocated())
00207     {
00208         return buffer->allocate();
00209     }
00210 
00211     return true;
00212 }
00213 
00214 cl_mem_flags MemObject::flags() const
00215 {
00216     return p_flags;
00217 }
00218 
00219 void *MemObject::host_ptr() const
00220 {
00221     if (type() != SubBuffer)
00222         return p_host_ptr;
00223     else
00224     {
00225         const class SubBuffer *subbuf = (const class SubBuffer *)this;
00226         char *tmp = (char *)subbuf->parent()->host_ptr();
00227 
00228         if (!tmp) return 0;
00229 
00230         tmp += subbuf->offset();
00231 
00232         return (void *)tmp;
00233     }
00234 }
00235 
00236 DeviceBuffer *MemObject::deviceBuffer(DeviceInterface *device) const
00237 {
00238     for (unsigned int i=0; i<p_num_devices; ++i)
00239     {
00240         if (p_devicebuffers[i]->device() == device)
00241             return p_devicebuffers[i];
00242     }
00243 
00244     return 0;
00245 }
00246 
00247 void MemObject::deviceAllocated(DeviceBuffer *buffer)
00248 {
00249     (void) buffer;
00250 
00251     // Decrement the count of devices that must be allocated. If it becomes
00252     // 0, it means we don't need to keep a copied host_ptr and that we can
00253     // std::free() it.
00254     p_devices_to_allocate--;
00255 
00256     if (p_devices_to_allocate == 0 &&
00257         p_num_devices > 1 &&
00258         (p_flags & CL_MEM_COPY_HOST_PTR))
00259     {
00260         std::free(p_host_ptr);
00261         p_host_ptr = 0;
00262     }
00263 
00264 }
00265 
00266 void MemObject::setDestructorCallback(void (CL_CALLBACK *pfn_notify)
00267                                                (cl_mem memobj, void *user_data),
00268                                       void *user_data)
00269 {
00270     p_dtor_callback = pfn_notify;
00271     p_dtor_userdata = user_data;
00272 }
00273 
00274 // HACK for the union
00275 typedef void * void_p;
00276 
00277 cl_int MemObject::info(cl_mem_info param_name,
00278                        size_t param_value_size,
00279                        void *param_value,
00280                        size_t *param_value_size_ret) const
00281 {
00282     void *value = 0;
00283     size_t value_length = 0;
00284     class SubBuffer *subbuf = (class SubBuffer *)this;
00285 
00286     union {
00287         cl_mem_object_type cl_mem_object_type_var;
00288         cl_mem_flags cl_mem_flags_var;
00289         size_t size_t_var;
00290         void_p void_p_var;
00291         cl_uint cl_uint_var;
00292         cl_context cl_context_var;
00293         cl_mem cl_mem_var;
00294     };
00295 
00296     switch (param_name)
00297     {
00298         case CL_MEM_TYPE:
00299             switch (type())
00300             {
00301                 case Buffer:
00302                 case SubBuffer:
00303                     cl_mem_object_type_var = CL_MEM_OBJECT_BUFFER;
00304                     break;
00305 
00306                 case Image2D:
00307                     cl_mem_object_type_var = CL_MEM_OBJECT_IMAGE2D;
00308                     break;
00309 
00310                 case Image3D:
00311                     cl_mem_object_type_var = CL_MEM_OBJECT_IMAGE3D;
00312                     break;
00313             }
00314             value = (void *)&cl_mem_object_type_var;
00315             value_length = sizeof(cl_mem_object_type);
00316             break;
00317 
00318         case CL_MEM_FLAGS:
00319             SIMPLE_ASSIGN(cl_mem_flags, p_flags);
00320             break;
00321 
00322         case CL_MEM_SIZE:
00323             SIMPLE_ASSIGN(size_t, size());
00324             break;
00325 
00326         case CL_MEM_HOST_PTR:
00327             SIMPLE_ASSIGN(void_p, host_ptr());
00328             break;
00329 
00330         case CL_MEM_MAP_COUNT:
00331             SIMPLE_ASSIGN(cl_uint, 0); // TODO
00332             break;
00333 
00334         case CL_MEM_REFERENCE_COUNT:
00335             SIMPLE_ASSIGN(cl_uint, references());
00336             break;
00337 
00338         case CL_MEM_CONTEXT:
00339             SIMPLE_ASSIGN(cl_context, parent());
00340             break;
00341 
00342         case CL_MEM_ASSOCIATED_MEMOBJECT:
00343             if (type() != SubBuffer)
00344                 SIMPLE_ASSIGN(cl_mem, 0)
00345             else
00346                 SIMPLE_ASSIGN(cl_mem, subbuf->parent());
00347             break;
00348 
00349         case CL_MEM_OFFSET:
00350             if (type() != SubBuffer)
00351                 SIMPLE_ASSIGN(cl_mem, 0)
00352             else
00353                 SIMPLE_ASSIGN(cl_mem, subbuf->offset());
00354             break;
00355 
00356         default:
00357             return CL_INVALID_VALUE;
00358     }
00359 
00360     if (param_value && param_value_size < value_length)
00361         return CL_INVALID_VALUE;
00362 
00363     if (param_value_size_ret)
00364         *param_value_size_ret = value_length;
00365 
00366     if (param_value)
00367         std::memcpy(param_value, value, value_length);
00368 
00369     return CL_SUCCESS;
00370 }
00371 
00372 /*
00373  * Buffer
00374  */
00375 
00376 Buffer::Buffer(Context *ctx, size_t size, void *host_ptr, cl_mem_flags flags,
00377                cl_int *errcode_ret)
00378 : MemObject(ctx, flags, host_ptr, errcode_ret), p_size(size)
00379 {
00380     if (size == 0)
00381     {
00382         *errcode_ret = CL_INVALID_BUFFER_SIZE;
00383         return;
00384     }
00385 }
00386 
00387 size_t Buffer::size() const
00388 {
00389     return p_size;
00390 }
00391 
00392 MemObject::Type Buffer::type() const
00393 {
00394     return MemObject::Buffer;
00395 }
00396 
00397 /*
00398  * SubBuffer
00399  */
00400 
00401 SubBuffer::SubBuffer(class Buffer *parent, size_t offset, size_t size,
00402                      cl_mem_flags flags, cl_int *errcode_ret)
00403 : MemObject((Context *)parent->parent(), flags, 0, errcode_ret), p_offset(offset),
00404   p_size(size), p_parent(parent)
00405 {
00406     if (size == 0)
00407     {
00408         *errcode_ret = CL_INVALID_BUFFER_SIZE;
00409         return;
00410     }
00411 
00412     if (offset + size > parent->size())
00413     {
00414         *errcode_ret = CL_INVALID_BUFFER_SIZE;
00415         return;
00416     }
00417 
00418     // Check the compatibility of flags and parent->flags()
00419     const cl_mem_flags wrong_flags =
00420         CL_MEM_ALLOC_HOST_PTR |
00421         CL_MEM_USE_HOST_PTR |
00422         CL_MEM_COPY_HOST_PTR;
00423 
00424     if (flags & wrong_flags)
00425     {
00426         *errcode_ret = CL_INVALID_VALUE;
00427         return;
00428     }
00429 
00430     if ((parent->flags() & CL_MEM_WRITE_ONLY) &&
00431         (flags & (CL_MEM_READ_WRITE | CL_MEM_READ_ONLY)))
00432     {
00433         *errcode_ret = CL_INVALID_VALUE;
00434         return;
00435     }
00436 
00437     if ((parent->flags() & CL_MEM_READ_ONLY) &&
00438         (flags & (CL_MEM_READ_WRITE | CL_MEM_WRITE_ONLY)))
00439     {
00440         *errcode_ret = CL_INVALID_VALUE;
00441         return;
00442     }
00443 }
00444 
00445 size_t SubBuffer::size() const
00446 {
00447     return p_size;
00448 }
00449 
00450 MemObject::Type SubBuffer::type() const
00451 {
00452     return MemObject::SubBuffer;
00453 }
00454 
00455 bool SubBuffer::allocate(DeviceInterface *device)
00456 {
00457     return p_parent->allocate(device);
00458 }
00459 
00460 size_t SubBuffer::offset() const
00461 {
00462     return p_offset;
00463 }
00464 
00465 Buffer *SubBuffer::parent() const
00466 {
00467     return p_parent;
00468 }
00469 
00470 /*
00471  * Image2D
00472  */
00473 
00474 Image2D::Image2D(Context *ctx, size_t width, size_t height, size_t row_pitch,
00475                  const cl_image_format *format, void *host_ptr,
00476                  cl_mem_flags flags, cl_int *errcode_ret)
00477 : MemObject(ctx, flags, host_ptr, errcode_ret),
00478   p_width(width), p_height(height), p_row_pitch(row_pitch)
00479 {
00480     if (!width || !height)
00481     {
00482         *errcode_ret = CL_INVALID_IMAGE_SIZE;
00483         return;
00484     }
00485 
00486     if (!format)
00487     {
00488         *errcode_ret = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
00489         return;
00490     }
00491 
00492     p_format = *format;
00493 
00494     // Check format descriptor
00495     switch (p_format.image_channel_data_type)
00496     {
00497         case CL_UNORM_INT_101010:
00498         case CL_UNORM_SHORT_555:
00499         case CL_UNORM_SHORT_565:
00500             if (p_format.image_channel_order != CL_RGB ||
00501                 p_format.image_channel_order != CL_RGBx)
00502             {
00503                 *errcode_ret = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
00504                 return;
00505             }
00506     }
00507 
00508     switch (p_format.image_channel_order)
00509     {
00510         case CL_LUMINANCE:
00511         case CL_INTENSITY:
00512             switch (p_format.image_channel_data_type)
00513             {
00514                 case CL_UNORM_INT8:
00515                 case CL_UNORM_INT16:
00516                 case CL_SNORM_INT8:
00517                 case CL_SNORM_INT16:
00518                 case CL_HALF_FLOAT:
00519                 case CL_FLOAT:
00520                     break;
00521                 default:
00522                     *errcode_ret = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
00523                     return;
00524             }
00525             break;
00526 
00527         case CL_RGB:
00528         case CL_RGBx:
00529             switch (p_format.image_channel_data_type)
00530             {
00531                 case CL_UNORM_SHORT_555:
00532                 case CL_UNORM_SHORT_565:
00533                 case CL_UNORM_INT_101010:
00534                     break;
00535                 default:
00536                     *errcode_ret = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
00537                     return;
00538             }
00539             break;
00540 
00541         case CL_ARGB:
00542         case CL_BGRA:
00543             switch (p_format.image_channel_data_type)
00544             {
00545                 case CL_UNORM_INT8:
00546                 case CL_SNORM_INT8:
00547                 case CL_SIGNED_INT8:
00548                 case CL_UNSIGNED_INT8:
00549                     break;
00550                 default:
00551                     *errcode_ret = CL_INVALID_IMAGE_FORMAT_DESCRIPTOR;
00552                     return;
00553             }
00554             break;
00555     }
00556 
00557     // Row pitch
00558     p_row_pitch = width * pixel_size(p_format);
00559 
00560     if (row_pitch)
00561     {
00562         if (!host_ptr)
00563         {
00564             // row_pitch must be 0 if host_ptr is null
00565             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00566             return;
00567         }
00568         if (row_pitch < p_row_pitch)
00569         {
00570             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00571             return;
00572         }
00573         if (row_pitch % pixel_size(p_format) != 0)
00574         {
00575             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00576             return;
00577         }
00578 
00579         p_row_pitch = row_pitch;
00580     }
00581 }
00582 
00583 size_t Image2D::size() const
00584 {
00585     return height() * row_pitch();
00586 }
00587 
00588 MemObject::Type Image2D::type() const
00589 {
00590     return MemObject::Image2D;
00591 }
00592 
00593 size_t Image2D::width() const
00594 {
00595     return p_width;
00596 }
00597 
00598 size_t Image2D::height() const
00599 {
00600     return p_height;
00601 }
00602 
00603 size_t Image2D::row_pitch() const
00604 {
00605     return p_row_pitch;
00606 }
00607 
00608 size_t Image2D::slice_pitch() const
00609 {
00610     // An Image2D is made of only one slice
00611     return size();
00612 }
00613 
00614 const cl_image_format &Image2D::format() const
00615 {
00616     return p_format;
00617 }
00618 
00619 cl_int Image2D::imageInfo(cl_image_info param_name,
00620                          size_t param_value_size,
00621                          void *param_value,
00622                          size_t *param_value_size_ret) const
00623 {
00624     void *value = 0;
00625     size_t value_length = 0;
00626     class Image3D *image3D = (class Image3D *)this;
00627 
00628     union {
00629         cl_image_format cl_image_format_var;
00630         size_t size_t_var;
00631     };
00632 
00633     switch (param_name)
00634     {
00635         case CL_IMAGE_FORMAT:
00636             SIMPLE_ASSIGN(cl_image_format, format());
00637             break;
00638 
00639         case CL_IMAGE_ELEMENT_SIZE:
00640             SIMPLE_ASSIGN(size_t, element_size(p_format));
00641             break;
00642 
00643         case CL_IMAGE_ROW_PITCH:
00644             // TODO: What was given when the image was created or width*size ?
00645             SIMPLE_ASSIGN(size_t, row_pitch());
00646             break;
00647 
00648         case CL_IMAGE_SLICE_PITCH:
00649             if (type() == Image3D)
00650                 SIMPLE_ASSIGN(size_t, image3D->slice_pitch())
00651             else
00652                 SIMPLE_ASSIGN(size_t, 0);
00653             break;
00654 
00655         case CL_IMAGE_WIDTH:
00656             SIMPLE_ASSIGN(size_t, width());
00657             break;
00658 
00659         case CL_IMAGE_HEIGHT:
00660             SIMPLE_ASSIGN(size_t, height());
00661             break;
00662 
00663         case CL_IMAGE_DEPTH:
00664             if (type() == Image3D)
00665                 SIMPLE_ASSIGN(size_t, image3D->depth())
00666             else
00667                 SIMPLE_ASSIGN(size_t, 0);
00668             break;
00669         default:
00670             return CL_INVALID_VALUE;
00671     }
00672 
00673     if (param_value && param_value_size < value_length)
00674         return CL_INVALID_VALUE;
00675 
00676     if (param_value_size_ret)
00677         *param_value_size_ret = value_length;
00678 
00679     if (param_value)
00680         std::memcpy(param_value, value, value_length);
00681 
00682     return CL_SUCCESS;
00683 }
00684 
00685 size_t Image2D::element_size(const cl_image_format &format)
00686 {
00687     switch (format.image_channel_data_type)
00688     {
00689         case CL_SNORM_INT8:
00690         case CL_UNORM_INT8:
00691         case CL_SIGNED_INT8:
00692         case CL_UNSIGNED_INT8:
00693             return 1;
00694         case CL_SNORM_INT16:
00695         case CL_UNORM_INT16:
00696         case CL_SIGNED_INT16:
00697         case CL_UNSIGNED_INT16:
00698             return 2;
00699         case CL_SIGNED_INT32:
00700         case CL_UNSIGNED_INT32:
00701             return 4;
00702         case CL_FLOAT:
00703             return sizeof(float);
00704         case CL_HALF_FLOAT:
00705             return 2;
00706         case CL_UNORM_SHORT_565:
00707         case CL_UNORM_SHORT_555:
00708             return 2;
00709         case CL_UNORM_INT_101010:
00710             return 4;
00711         default:
00712             return 0;
00713     }
00714 }
00715 
00716 unsigned int Image2D::channels(const cl_image_format &format)
00717 {
00718     switch (format.image_channel_order)
00719     {
00720         case CL_R:
00721         case CL_Rx:
00722         case CL_A:
00723         case CL_INTENSITY:
00724         case CL_LUMINANCE:
00725             return 1;
00726             break;
00727 
00728         case CL_RG:
00729         case CL_RGx:
00730         case CL_RA:
00731             return 2;
00732             break;
00733 
00734         case CL_RGBA:
00735         case CL_ARGB:
00736         case CL_BGRA:
00737             return 4;
00738             break;
00739 
00740         case CL_RGBx:
00741         case CL_RGB:
00742             return 1; // Only special data types allowed (565, 555, etc)
00743             break;
00744 
00745         default:
00746             return 0;
00747     }
00748 }
00749 
00750 size_t Image2D::pixel_size(const cl_image_format &format)
00751 {
00752     switch (format.image_channel_data_type)
00753     {
00754         case CL_UNORM_SHORT_565:
00755         case CL_UNORM_SHORT_555:
00756             return 2;
00757         case CL_UNORM_INT_101010:
00758             return 4;
00759         default:
00760             return channels(format) * element_size(format);
00761     }
00762 }
00763 
00764 size_t Image2D::element_size() const
00765 {
00766     return element_size(p_format);
00767 }
00768 
00769 size_t Image2D::pixel_size() const
00770 {
00771     return pixel_size(p_format);
00772 }
00773 
00774 unsigned int Image2D::channels() const
00775 {
00776     return channels(p_format);
00777 }
00778 
00779 /*
00780  * Image3D
00781  */
00782 
00783 Image3D::Image3D(Context *ctx, size_t width, size_t height, size_t depth,
00784                  size_t row_pitch, size_t slice_pitch,
00785                  const cl_image_format *format, void *host_ptr,
00786                  cl_mem_flags flags, cl_int *errcode_ret)
00787 : Image2D(ctx, width, height, row_pitch, format, host_ptr, flags, errcode_ret),
00788   p_depth(depth)
00789 {
00790     if (depth <= 1)
00791     {
00792         *errcode_ret = CL_INVALID_IMAGE_SIZE;
00793         return;
00794     }
00795 
00796     // Slice pitch
00797     p_slice_pitch = height * this->row_pitch();
00798 
00799     if (slice_pitch)
00800     {
00801         if (!host_ptr)
00802         {
00803             // slice_pitch must be 0 if host_ptr is null
00804             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00805             return;
00806         }
00807         if (slice_pitch < p_slice_pitch)
00808         {
00809             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00810             return;
00811         }
00812         if (slice_pitch % this->row_pitch() != 0)
00813         {
00814             *errcode_ret = CL_INVALID_IMAGE_SIZE;
00815             return;
00816         }
00817 
00818         p_slice_pitch = slice_pitch;
00819     }
00820 }
00821 
00822 size_t Image3D::size() const
00823 {
00824     return depth() * slice_pitch();
00825 }
00826 
00827 MemObject::Type Image3D::type() const
00828 {
00829     return MemObject::Image3D;
00830 }
00831 
00832 size_t Image3D::depth() const
00833 {
00834     return p_depth;
00835 }
00836 
00837 size_t Image3D::slice_pitch() const
00838 {
00839     return p_slice_pitch;
00840 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines