SkelCL
SkelCL is a high level multi GPU skeleton library developed at the university of Münster, Germany.
 All Classes Namespaces Files Functions Variables Typedefs Groups
DeviceBuffer.cpp
1 /*****************************************************************************
2  * Copyright (c) 2011-2012 The SkelCL Team as listed in CREDITS.txt *
3  * http://skelcl.uni-muenster.de *
4  * *
5  * This file is part of SkelCL. *
6  * SkelCL is available under multiple licenses. *
7  * The different licenses are subject to terms and condition as provided *
8  * in the files specifying the license. See "LICENSE.txt" for details *
9  * *
10  *****************************************************************************
11  * *
12  * SkelCL is free software: you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation, either version 3 of the License, or *
15  * (at your option) any later version. See "LICENSE-gpl.txt" for details. *
16  * *
17  * SkelCL is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  *****************************************************************************
23  * *
24  * For non-commercial academic use see the license specified in the file *
25  * "LICENSE-academic.txt". *
26  * *
27  *****************************************************************************
28  * *
29  * If you are interested in other licensing models, including a commercial- *
30  * license, please contact the author at michel.steuwer@uni-muenster.de *
31  * *
32  *****************************************************************************/
33 
39 
40 #include <sstream>
41 #include <string>
42 #include <memory>
43 
44 #define __CL_ENABLE_EXCEPTIONS
45 #include <CL/cl.hpp>
46 #undef __CL_ENABLE_EXCEPTIONS
47 
48 #include <pvsutil/Assert.h>
49 #include <pvsutil/Logger.h>
50 
51 #include "SkelCL/detail/DeviceBuffer.h"
52 
53 #include "SkelCL/detail/Device.h"
54 #include "SkelCL/detail/DeviceList.h"
55 
56 namespace {
57 
58 using namespace skelcl::detail;
59 
60 cl::Buffer createCLBuffer(const std::shared_ptr<Device>& devicePtr,
61  const size_t size,
62  const size_t elemSize,
63  cl_mem_flags flags) {
64  cl::Buffer buffer;
65  try {
66  buffer = cl::Buffer(devicePtr->clContext(), flags, size * elemSize);
67  } catch (cl::Error& err) {
68  ABORT_WITH_ERROR(err);
69  }
70  return buffer;
71 }
72 
73 } // namespace
74 
75 namespace skelcl {
76 
77 namespace detail {
78 
79 DeviceBuffer::DeviceBuffer()
80  : _device(), _size(), _elemSize(), _flags(), _buffer()
81 {
82 }
83 
84 DeviceBuffer::DeviceBuffer(const std::shared_ptr<Device>& devicePtr,
85  const size_t size,
86  const size_t elemSize,
87  cl_mem_flags flags)
88  : _device(devicePtr),
89  _size(size),
90  _elemSize(elemSize),
91  _flags(flags),
92  _buffer(::createCLBuffer(_device, _size, _elemSize, _flags))
93 {
94  LOG_DEBUG_INFO("Created new DeviceBuffer object (", this, ") with ",
95  getInfo());
96 }
97 
98 DeviceBuffer::DeviceBuffer(const DeviceBuffer& rhs)
99  : _device(rhs._device),
100  _size(rhs._size),
101  _elemSize(rhs._elemSize),
102  _flags(rhs._flags),
103  _buffer()
104 {
105  // make deep copy of the rhs buffer
106  _buffer = ::createCLBuffer(_device, _size, _elemSize, _flags);
107  _device->enqueueCopy(rhs, *this);
108 
109  LOG_DEBUG_INFO("Created new DeviceBuffer object (", this, ") by copying (",
110  &rhs, ") with ", getInfo());
111 }
112 
113 DeviceBuffer::DeviceBuffer(DeviceBuffer&& rhs)
114  : _device(std::move(rhs._device)),
115  _size(std::move(rhs._size)),
116  _elemSize(std::move(rhs._elemSize)),
117  _flags(std::move(rhs._flags)),
118  _buffer(std::move(rhs._buffer)) // only wrapper object (pointer) is copied
119 {
120  rhs._size = 0;
121  rhs._elemSize = 0;
122  rhs._buffer = cl::Buffer();
123  LOG_DEBUG_INFO("Created new DeviceBuffer object (", this, ") by moving with ",
124  getInfo());
125 }
126 
127 DeviceBuffer& DeviceBuffer::operator=(const DeviceBuffer& rhs)
128 {
129  if (this == &rhs) return *this; // handle self assignement
130  _device = rhs._device;
131  _size = rhs._size;
132  _elemSize = rhs._elemSize;
133  _flags = rhs._flags;
134  // make deep copy of the rhs buffer
135  _buffer = ::createCLBuffer(_device, _size, _elemSize, _flags);
136  _device->enqueueCopy(rhs, *this);
137 
138  LOG_DEBUG_INFO("Assignement to DeviceBuffer object (", this, ") now with ",
139  getInfo());
140  return *this;
141 }
142 
143 DeviceBuffer& DeviceBuffer::operator=(DeviceBuffer&& rhs)
144 {
145  if (this == &rhs) return *this;
146  _device = std::move(rhs._device);
147  _size = std::move(rhs._size);
148  _elemSize = std::move(rhs._elemSize);
149  _flags = std::move(rhs._flags);
150  _buffer = std::move(rhs._buffer); // copy only wrapper object (pointer)
151 
152  rhs._size = 0;
153  rhs._elemSize = 0;
154  rhs._buffer = cl::Buffer();
155  LOG_DEBUG_INFO("Move assignment to DeviceBuffer object (", this,
156  ") now with ", getInfo());
157  return *this;
158 }
159 
160 DeviceBuffer::~DeviceBuffer()
161 {
162  if (_size == 0) {
163  LOG_DEBUG_INFO("Empty DeviceBuffer object (", this, ") destroyed");
164  } else {
165  LOG_DEBUG_INFO("DeviceBuffer object (", this, ") destroyed");
166  }
167  if (_buffer() != nullptr) {
168  auto refCount = _buffer.getInfo<CL_MEM_REFERENCE_COUNT>();
169  if (refCount > 1) {
170  LOG_DEBUG_INFO("OpenCL Buffer object remains alive (Ref count ",
171  refCount, ")");
172  }
173  }
174 }
175 
176 std::shared_ptr<Device> DeviceBuffer::devicePtr() const
177 {
178  return _device;
179 }
180 
181 DeviceBuffer::size_type DeviceBuffer::size() const
182 {
183  return _size;
184 }
185 
186 DeviceBuffer::size_type DeviceBuffer::elemSize() const
187 {
188  return _elemSize;
189 }
190 
191 DeviceBuffer::size_type DeviceBuffer::sizeInBytes() const
192 {
193  return _size * _elemSize;
194 }
195 
196 const cl::Buffer& DeviceBuffer::clBuffer() const
197 {
198  return _buffer;
199 }
200 
201 bool DeviceBuffer::isValid() const
202 {
203  return (_buffer() != NULL);
204 }
205 
206 std::string DeviceBuffer::getInfo() const
207 {
208  std::stringstream s;
209  s << "device: " << _device->id()
210  << ", size: " << _size
211  << ", flags: " << _flags
212  << ", buffer: " << _buffer();
213  return s.str();
214 }
215 
216 } // namespace detail
217 
218 } // namespace skelcl
219