-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathOpenClBufferManager.cpp
141 lines (125 loc) · 4.72 KB
/
OpenClBufferManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// Copyright (c) 2013-2014 Josh Blum
// SPDX-License-Identifier: BSL-1.0
#include "OpenClKernel.hpp"
#include <Pothos/Plugin.hpp>
#include <Pothos/Util/RingDeque.hpp>
#include <Pothos/Framework/BufferManager.hpp>
#include <cassert>
#include <iostream>
/***********************************************************************
* The OpenClBufferContainer allocates and maps a buffer.
* It knows how to cleanup when the buffer dereferences.
**********************************************************************/
class OpenClBufferContainer
{
public:
OpenClBufferContainer(const OpenClBufferContainerArgs &clArgs, const size_t bufferSize):
_clArgs(clArgs)
{
cl_int err = 0;
memobj = clCreateBuffer(*_clArgs.context, _clArgs.mem_flags, bufferSize, nullptr, &err);
if (err < 0) throw Pothos::Exception("OpenClBufferContainer::clCreateBuffer()", clErrToStr(err));
mapped_ptr = clEnqueueMapBuffer(
*_clArgs.queue,
memobj,
CL_TRUE, /*blocking map*/
_clArgs.map_flags,
0, //offset
bufferSize,
0, nullptr, nullptr,
&err);
if (err < 0) throw Pothos::Exception("OpenClBufferContainer::clEnqueueMapBuffer()", clErrToStr(err));
}
~OpenClBufferContainer(void)
{
clEnqueueUnmapMemObject(*_clArgs.queue, memobj, mapped_ptr, 0, nullptr, nullptr);
clReleaseMemObject(memobj);
}
void *mapped_ptr;
cl_mem memobj;
private:
OpenClBufferContainerArgs _clArgs;
};
/***********************************************************************
* Custom buffer manager for dealing with opencl mapped buffers
**********************************************************************/
class OpenClBufferManager :
public Pothos::BufferManager,
public std::enable_shared_from_this<OpenClBufferManager>
{
public:
OpenClBufferManager(const OpenClBufferContainerArgs &clArgs):
_clArgs(clArgs)
{
return;
}
void init(const Pothos::BufferManagerArgs &args)
{
Pothos::BufferManager::init(args);
_readyBuffs.set_capacity(args.numBuffers);
for (size_t i = 0; i < args.numBuffers; i++)
{
auto container = std::make_shared<OpenClBufferContainer>(_clArgs, args.bufferSize);
auto sharedBuff = Pothos::SharedBuffer(size_t(container->mapped_ptr), args.bufferSize, container);
Pothos::ManagedBuffer buffer;
buffer.reset(this->shared_from_this(), sharedBuff);
}
}
bool empty(void) const
{
return _readyBuffs.empty();
}
void pop(const size_t numBytes)
{
assert(not _readyBuffs.empty());
auto buff = _readyBuffs.front();
_readyBuffs.pop_front();
if (_readyBuffs.empty()) this->setFrontBuffer(Pothos::BufferChunk::null());
else this->setFrontBuffer(_readyBuffs.front());
auto container = std::static_pointer_cast<OpenClBufferContainer>(buff.getBuffer().getContainer());
assert(container);
//perform non blocking write
//kernel will be enqueued after this
if (_clArgs.map_flags == CL_MAP_WRITE)
{
const cl_int err = clEnqueueWriteBuffer(
*_clArgs.queue,
container->memobj, CL_FALSE, 0,
numBytes, container->mapped_ptr,
0, nullptr, nullptr
);
if (err < 0) throw Pothos::Exception("OpenClBufferManager::clEnqueueWriteBuffer()", clErrToStr(err));
}
//perform blocking read
//must block before giving downstream memory
if (_clArgs.map_flags == CL_MAP_READ)
{
const cl_int err = clEnqueueReadBuffer(
*_clArgs.queue,
container->memobj, CL_TRUE, 0,
numBytes, container->mapped_ptr,
0, nullptr, nullptr
);
if (err < 0) throw Pothos::Exception("OpenClBufferManager::clEnqueueReadBuffer()", clErrToStr(err));
}
}
void push(const Pothos::ManagedBuffer &buff)
{
if (_readyBuffs.empty()) this->setFrontBuffer(buff);
auto container = std::static_pointer_cast<OpenClBufferContainer>(buff.getBuffer().getContainer());
assert(container);
assert(not _readyBuffs.full());
_readyBuffs.push_back(buff);
}
private:
Pothos::Util::RingDeque<Pothos::ManagedBuffer> _readyBuffs;
OpenClBufferContainerArgs _clArgs;
};
Pothos::BufferManager::Sptr makeOpenClBufferManager(const OpenClBufferContainerArgs &args)
{
return std::make_shared<OpenClBufferManager>(args);
}
cl_mem &getClBufferFromManaged(const Pothos::ManagedBuffer &buff)
{
return std::static_pointer_cast<OpenClBufferContainer>(buff.getBuffer().getContainer())->memobj;
}