Clover Git
OpenCL 1.1 software implementation
|
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 }