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
26using namespace clover;
27
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
37_cl_mem::~_cl_mem() {
38   __destroy_notify();
39}
40
41void
42_cl_mem::destroy_notify(std::function<void ()> f) {
43   __destroy_notify = f;
44}
45
46cl_mem_flags
47_cl_mem::flags() const {
48   return __flags;
49}
50
51size_t
52_cl_mem::size() const {
53   return __size;
54}
55
56void *
57_cl_mem::host_ptr() const {
58   return __host_ptr;
59}
60
61buffer::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
66cl_mem_object_type
67buffer::type() const {
68   return CL_MEM_OBJECT_BUFFER;
69}
70
71root_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
76clover::resource &
77root_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
92sub_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
99clover::resource &
100sub_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
112size_t
113sub_buffer::offset() const {
114   return __offset;
115}
116
117image::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
127clover::resource &
128image::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
143cl_image_format
144image::format() const {
145   return __format;
146}
147
148size_t
149image::width() const {
150   return __width;
151}
152
153size_t
154image::height() const {
155   return __height;
156}
157
158size_t
159image::depth() const {
160   return __depth;
161}
162
163size_t
164image::row_pitch() const {
165   return __row_pitch;
166}
167
168size_t
169image::slice_pitch() const {
170   return __slice_pitch;
171}
172
173image2d::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
181cl_mem_object_type
182image2d::type() const {
183   return CL_MEM_OBJECT_IMAGE2D;
184}
185
186image3d::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
196cl_mem_object_type
197image3d::type() const {
198   return CL_MEM_OBJECT_IMAGE3D;
199}
200