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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 // OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 // SOFTWARE.
21 //
22 
23 #include "core/memory.hpp"
24 #include "core/resource.hpp"
25 
26 using namespace clover;
27 
_cl_mem(clover::context & ctx,cl_mem_flags flags,size_t size,void * host_ptr)28 _cl_mem::_cl_mem(clover::context &ctx, cl_mem_flags flags,
29                  size_t size, void *host_ptr) :
30    ctx(ctx), __flags(flags),
31    __size(size), __host_ptr(host_ptr),
32    __destroy_notify([]{}) {
33    if (flags & CL_MEM_COPY_HOST_PTR)
34       data.append((char *)host_ptr, size);
35 }
36 
~_cl_mem()37 _cl_mem::~_cl_mem() {
38    __destroy_notify();
39 }
40 
41 void
destroy_notify(std::function<void ()> f)42 _cl_mem::destroy_notify(std::function<void ()> f) {
43    __destroy_notify = f;
44 }
45 
46 cl_mem_flags
flags() const47 _cl_mem::flags() const {
48    return __flags;
49 }
50 
51 size_t
size() const52 _cl_mem::size() const {
53    return __size;
54 }
55 
56 void *
host_ptr() const57 _cl_mem::host_ptr() const {
58    return __host_ptr;
59 }
60 
buffer(clover::context & ctx,cl_mem_flags flags,size_t size,void * host_ptr)61 buffer::buffer(clover::context &ctx, cl_mem_flags flags,
62                size_t size, void *host_ptr) :
63    memory_obj(ctx, flags, size, host_ptr) {
64 }
65 
66 cl_mem_object_type
type() const67 buffer::type() const {
68    return CL_MEM_OBJECT_BUFFER;
69 }
70 
root_buffer(clover::context & ctx,cl_mem_flags flags,size_t size,void * host_ptr)71 root_buffer::root_buffer(clover::context &ctx, cl_mem_flags flags,
72                          size_t size, void *host_ptr) :
73    buffer(ctx, flags, size, host_ptr) {
74 }
75 
76 clover::resource &
resource(cl_command_queue q)77 root_buffer::resource(cl_command_queue q) {
78    // Create a new resource if there's none for this device yet.
79    if (!resources.count(&q->dev)) {
80       auto r = (!resources.empty() ?
81                 new root_resource(q->dev, *this, *resources.begin()->second) :
82                 new root_resource(q->dev, *this, *q, data));
83 
84       resources.insert(std::make_pair(&q->dev,
85                                       std::unique_ptr<root_resource>(r)));
86       data.clear();
87    }
88 
89    return *resources.find(&q->dev)->second;
90 }
91 
sub_buffer(clover::root_buffer & parent,cl_mem_flags flags,size_t offset,size_t size)92 sub_buffer::sub_buffer(clover::root_buffer &parent, cl_mem_flags flags,
93                        size_t offset, size_t size) :
94    buffer(parent.ctx, flags, size,
95           (char *)parent.host_ptr() + offset),
96    parent(parent), __offset(offset) {
97 }
98 
99 clover::resource &
resource(cl_command_queue q)100 sub_buffer::resource(cl_command_queue q) {
101    // Create a new resource if there's none for this device yet.
102    if (!resources.count(&q->dev)) {
103       auto r = new sub_resource(parent.resource(q), { offset() });
104 
105       resources.insert(std::make_pair(&q->dev,
106                                       std::unique_ptr<sub_resource>(r)));
107    }
108 
109    return *resources.find(&q->dev)->second;
110 }
111 
112 size_t
offset() const113 sub_buffer::offset() const {
114    return __offset;
115 }
116 
image(clover::context & ctx,cl_mem_flags flags,const cl_image_format * format,size_t width,size_t height,size_t depth,size_t row_pitch,size_t slice_pitch,size_t size,void * host_ptr)117 image::image(clover::context &ctx, cl_mem_flags flags,
118              const cl_image_format *format,
119              size_t width, size_t height, size_t depth,
120              size_t row_pitch, size_t slice_pitch, size_t size,
121              void *host_ptr) :
122    memory_obj(ctx, flags, size, host_ptr),
123    __format(*format), __width(width), __height(height), __depth(depth),
124    __row_pitch(row_pitch), __slice_pitch(slice_pitch) {
125 }
126 
127 clover::resource &
resource(cl_command_queue q)128 image::resource(cl_command_queue q) {
129    // Create a new resource if there's none for this device yet.
130    if (!resources.count(&q->dev)) {
131       auto r = (!resources.empty() ?
132                 new root_resource(q->dev, *this, *resources.begin()->second) :
133                 new root_resource(q->dev, *this, *q, data));
134 
135       resources.insert(std::make_pair(&q->dev,
136                                       std::unique_ptr<root_resource>(r)));
137       data.clear();
138    }
139 
140    return *resources.find(&q->dev)->second;
141 }
142 
143 cl_image_format
format() const144 image::format() const {
145    return __format;
146 }
147 
148 size_t
width() const149 image::width() const {
150    return __width;
151 }
152 
153 size_t
height() const154 image::height() const {
155    return __height;
156 }
157 
158 size_t
depth() const159 image::depth() const {
160    return __depth;
161 }
162 
163 size_t
row_pitch() const164 image::row_pitch() const {
165    return __row_pitch;
166 }
167 
168 size_t
slice_pitch() const169 image::slice_pitch() const {
170    return __slice_pitch;
171 }
172 
image2d(clover::context & ctx,cl_mem_flags flags,const cl_image_format * format,size_t width,size_t height,size_t row_pitch,void * host_ptr)173 image2d::image2d(clover::context &ctx, cl_mem_flags flags,
174                  const cl_image_format *format, size_t width,
175                  size_t height, size_t row_pitch,
176                  void *host_ptr) :
177    image(ctx, flags, format, width, height, 0,
178          row_pitch, 0, height * row_pitch, host_ptr) {
179 }
180 
181 cl_mem_object_type
type() const182 image2d::type() const {
183    return CL_MEM_OBJECT_IMAGE2D;
184 }
185 
image3d(clover::context & ctx,cl_mem_flags flags,const cl_image_format * format,size_t width,size_t height,size_t depth,size_t row_pitch,size_t slice_pitch,void * host_ptr)186 image3d::image3d(clover::context &ctx, cl_mem_flags flags,
187                  const cl_image_format *format,
188                  size_t width, size_t height, size_t depth,
189                  size_t row_pitch, size_t slice_pitch,
190                  void *host_ptr) :
191    image(ctx, flags, format, width, height, depth,
192          row_pitch, slice_pitch, depth * slice_pitch,
193          host_ptr) {
194 }
195 
196 cl_mem_object_type
type() const197 image3d::type() const {
198    return CL_MEM_OBJECT_IMAGE3D;
199 }
200