1 // 2 // Copyright 2012 Francisco Jerez 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 // OTHER DEALINGS IN THE SOFTWARE. 21 // 22 23 #include "core/memory.hpp" 24 #include "core/resource.hpp" 25 #include "util/u_format.h" 26 27 using namespace clover; 28 29 memory_obj::memory_obj(clover::context &ctx, cl_mem_flags flags, 30 size_t size, void *host_ptr) : 31 context(ctx), _flags(flags), 32 _size(size), _host_ptr(host_ptr) { 33 if (flags & CL_MEM_COPY_HOST_PTR) 34 data.append((char *)host_ptr, size); 35 } 36 37 memory_obj::~memory_obj() { 38 while (_destroy_notify.size()) { 39 _destroy_notify.top()(); 40 _destroy_notify.pop(); 41 } 42 } 43 44 bool 45 memory_obj::operator==(const memory_obj &obj) const { 46 return this == &obj; 47 } 48 49 void 50 memory_obj::destroy_notify(std::function<void ()> f) { 51 _destroy_notify.push(f); 52 } 53 54 cl_mem_flags 55 memory_obj::flags() const { 56 return _flags; 57 } 58 59 size_t 60 memory_obj::size() const { 61 return _size; 62 } 63 64 void * 65 memory_obj::host_ptr() const { 66 return _host_ptr; 67 } 68 69 buffer::buffer(clover::context &ctx, cl_mem_flags flags, 70 size_t size, void *host_ptr) : 71 memory_obj(ctx, flags, size, host_ptr) { 72 } 73 74 cl_mem_object_type 75 buffer::type() const { 76 return CL_MEM_OBJECT_BUFFER; 77 } 78 79 root_buffer::root_buffer(clover::context &ctx, cl_mem_flags flags, 80 size_t size, void *host_ptr) : 81 buffer(ctx, flags, size, host_ptr) { 82 } 83 84 resource & 85 root_buffer::resource(command_queue &q) { 86 // Create a new resource if there's none for this device yet. 87 if (!resources.count(&q.device())) { 88 auto r = (!resources.empty() ? 89 new root_resource(q.device(), *this, 90 *resources.begin()->second) : 91 new root_resource(q.device(), *this, q, data)); 92 93 resources.insert(std::make_pair(&q.device(), 94 std::unique_ptr<root_resource>(r))); 95 data.clear(); 96 } 97 98 return *resources.find(&q.device())->second; 99 } 100 101 sub_buffer::sub_buffer(root_buffer &parent, cl_mem_flags flags, 102 size_t offset, size_t size) : 103 buffer(parent.context(), flags, size, 104 (char *)parent.host_ptr() + offset), 105 parent(parent), _offset(offset) { 106 } 107 108 resource & 109 sub_buffer::resource(command_queue &q) { 110 // Create a new resource if there's none for this device yet. 111 if (!resources.count(&q.device())) { 112 auto r = new sub_resource(parent().resource(q), {{ offset() }}); 113 114 resources.insert(std::make_pair(&q.device(), 115 std::unique_ptr<sub_resource>(r))); 116 } 117 118 return *resources.find(&q.device())->second; 119 } 120 121 size_t 122 sub_buffer::offset() const { 123 return _offset; 124 } 125 126 image::image(clover::context &ctx, cl_mem_flags flags, 127 const cl_image_format *format, 128 size_t width, size_t height, size_t depth, 129 size_t row_pitch, size_t slice_pitch, size_t size, 130 void *host_ptr) : 131 memory_obj(ctx, flags, size, host_ptr), 132 _format(*format), _width(width), _height(height), _depth(depth), 133 _row_pitch(row_pitch), _slice_pitch(slice_pitch) { 134 } 135 136 resource & 137 image::resource(command_queue &q) { 138 // Create a new resource if there's none for this device yet. 139 if (!resources.count(&q.device())) { 140 auto r = (!resources.empty() ? 141 new root_resource(q.device(), *this, 142 *resources.begin()->second) : 143 new root_resource(q.device(), *this, q, data)); 144 145 resources.insert(std::make_pair(&q.device(), 146 std::unique_ptr<root_resource>(r))); 147 data.clear(); 148 } 149 150 return *resources.find(&q.device())->second; 151 } 152 153 cl_image_format 154 image::format() const { 155 return _format; 156 } 157 158 size_t 159 image::width() const { 160 return _width; 161 } 162 163 size_t 164 image::height() const { 165 return _height; 166 } 167 168 size_t 169 image::depth() const { 170 return _depth; 171 } 172 173 size_t 174 image::pixel_size() const { 175 return util_format_get_blocksize(translate_format(_format)); 176 } 177 178 size_t 179 image::row_pitch() const { 180 return _row_pitch; 181 } 182 183 size_t 184 image::slice_pitch() const { 185 return _slice_pitch; 186 } 187 188 image2d::image2d(clover::context &ctx, cl_mem_flags flags, 189 const cl_image_format *format, size_t width, 190 size_t height, size_t row_pitch, 191 void *host_ptr) : 192 image(ctx, flags, format, width, height, 1, 193 row_pitch, 0, height * row_pitch, host_ptr) { 194 } 195 196 cl_mem_object_type 197 image2d::type() const { 198 return CL_MEM_OBJECT_IMAGE2D; 199 } 200 201 image3d::image3d(clover::context &ctx, cl_mem_flags flags, 202 const cl_image_format *format, 203 size_t width, size_t height, size_t depth, 204 size_t row_pitch, size_t slice_pitch, 205 void *host_ptr) : 206 image(ctx, flags, format, width, height, depth, 207 row_pitch, slice_pitch, depth * slice_pitch, 208 host_ptr) { 209 } 210 211 cl_mem_object_type 212 image3d::type() const { 213 return CL_MEM_OBJECT_IMAGE3D; 214 } 215