blob: 835958b8165d6c5bf3759ea4a75878f6eed87b32 [file] [log] [blame]
Georgios Pinitas99d40952018-04-23 16:26:46 +01001/*
SiCong Lia359ee92023-04-18 13:49:56 +01002 * Copyright (c) 2018-2021, 2023 Arm Limited.
Georgios Pinitas99d40952018-04-23 16:26:46 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/runtime/CL/CLMemoryRegion.h"
25
26#include "arm_compute/core/Error.h"
27#include "arm_compute/runtime/CL/CLScheduler.h"
28
29namespace arm_compute
30{
Georgios Pinitas2cd5b312021-05-04 21:39:57 +010031ICLMemoryRegion::ICLMemoryRegion(size_t size)
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010032 : IMemoryRegion(size), _ctx(CLScheduler::get().context()), _mapping(nullptr), _mem()
Georgios Pinitas99d40952018-04-23 16:26:46 +010033{
34}
35
36const cl::Buffer &ICLMemoryRegion::cl_data() const
37{
38 return _mem;
39}
40
41void *ICLMemoryRegion::buffer()
42{
43 return _mapping;
44}
45
Georgios Pinitas74ef1db2020-01-20 17:01:15 +000046const void *ICLMemoryRegion::buffer() const
Georgios Pinitas99d40952018-04-23 16:26:46 +010047{
48 return _mapping;
49}
50
Georgios Pinitasdf310362018-11-14 13:16:56 +000051std::unique_ptr<IMemoryRegion> ICLMemoryRegion::extract_subregion(size_t offset, size_t size)
Georgios Pinitas99d40952018-04-23 16:26:46 +010052{
Georgios Pinitasdf310362018-11-14 13:16:56 +000053 ARM_COMPUTE_UNUSED(offset, size);
54 return nullptr;
Georgios Pinitas99d40952018-04-23 16:26:46 +010055}
56
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010057CLBufferMemoryRegion::CLBufferMemoryRegion(cl_mem_flags flags, size_t size) : ICLMemoryRegion(size)
Georgios Pinitas99d40952018-04-23 16:26:46 +010058{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010059 if (_size != 0)
Georgios Pinitas99d40952018-04-23 16:26:46 +010060 {
Georgios Pinitas2cd5b312021-05-04 21:39:57 +010061 _mem = cl::Buffer(CLScheduler::get().context(), flags, _size);
Georgios Pinitas99d40952018-04-23 16:26:46 +010062 }
63}
64
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010065CLBufferMemoryRegion::CLBufferMemoryRegion(const cl::Buffer &buffer) : ICLMemoryRegion(buffer.getInfo<CL_MEM_SIZE>())
Georgios Pinitasdf310362018-11-14 13:16:56 +000066{
67 _mem = buffer;
68}
69
SiCong Li7d91c612023-08-11 17:58:56 +010070CLBufferMemoryRegion::~CLBufferMemoryRegion()
71{
72 // Flush the command queue to ensure all commands that may use this memory buffer are scheduled to be finished before
73 // this buffer is freed
74 // Do not call finish as it is a blocking call which affects the performance
75 CLScheduler::get().queue().flush();
76}
77
Georgios Pinitas99d40952018-04-23 16:26:46 +010078void *CLBufferMemoryRegion::ptr()
79{
80 return nullptr;
81}
82
83void *CLBufferMemoryRegion::map(cl::CommandQueue &q, bool blocking)
84{
85 ARM_COMPUTE_ERROR_ON(_mem.get() == nullptr);
86 _mapping = q.enqueueMapBuffer(_mem, blocking ? CL_TRUE : CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, 0, _size);
87 return _mapping;
88}
89
90void CLBufferMemoryRegion::unmap(cl::CommandQueue &q)
91{
92 ARM_COMPUTE_ERROR_ON(_mem.get() == nullptr);
93 q.enqueueUnmapMemObject(_mem, _mapping);
94 _mapping = nullptr;
95}
96
Georgios Pinitas2cd5b312021-05-04 21:39:57 +010097ICLSVMMemoryRegion::ICLSVMMemoryRegion(cl_mem_flags flags, size_t size, size_t alignment)
98 : ICLMemoryRegion(size), _ptr(nullptr)
Georgios Pinitas99d40952018-04-23 16:26:46 +010099{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100100 if (size != 0)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100101 {
Georgios Pinitas2cd5b312021-05-04 21:39:57 +0100102 _ptr = clSVMAlloc(CLScheduler::get().context().get(), flags, size, alignment);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100103 if (_ptr != nullptr)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100104 {
Georgios Pinitas2cd5b312021-05-04 21:39:57 +0100105 _mem = cl::Buffer(CLScheduler::get().context(), CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, _size, _ptr);
Georgios Pinitas99d40952018-04-23 16:26:46 +0100106 }
107 }
108}
109
110ICLSVMMemoryRegion::~ICLSVMMemoryRegion()
111{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100112 if (_ptr != nullptr)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100113 {
Georgios Pinitas5a1320b2019-06-27 17:50:43 +0100114 try
115 {
SiCong Li7d91c612023-08-11 17:58:56 +0100116 // Can only use the blocking finish instead of the non-blocking flush here, because clSVMFree requires all
117 // commands that may use the svm pointer to finish beforehand
118 // https://registry.khronos.org/OpenCL/sdk/3.0/docs/man/html/clSVMFree.html
SiCong Lia359ee92023-04-18 13:49:56 +0100119 clFinish(CLScheduler::get().queue().get());
Georgios Pinitas5a1320b2019-06-27 17:50:43 +0100120 _mem = cl::Buffer();
121 clSVMFree(_ctx.get(), _ptr);
122 }
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100123 catch (...)
Georgios Pinitas5a1320b2019-06-27 17:50:43 +0100124 {
125 }
Georgios Pinitas99d40952018-04-23 16:26:46 +0100126 }
127}
128
129void *ICLSVMMemoryRegion::ptr()
130{
131 return _ptr;
132}
133
Georgios Pinitas2cd5b312021-05-04 21:39:57 +0100134CLCoarseSVMMemoryRegion::CLCoarseSVMMemoryRegion(cl_mem_flags flags, size_t size, size_t alignment)
135 : ICLSVMMemoryRegion(flags, size, alignment)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100136{
137}
138
139void *CLCoarseSVMMemoryRegion::map(cl::CommandQueue &q, bool blocking)
140{
141 ARM_COMPUTE_ERROR_ON(_ptr == nullptr);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100142 clEnqueueSVMMap(q.get(), blocking ? CL_TRUE : CL_FALSE, CL_MAP_READ | CL_MAP_WRITE, _ptr, _size, 0, nullptr,
143 nullptr);
Georgios Pinitas99d40952018-04-23 16:26:46 +0100144 _mapping = _ptr;
145 return _mapping;
146}
147
148void CLCoarseSVMMemoryRegion::unmap(cl::CommandQueue &q)
149{
150 ARM_COMPUTE_ERROR_ON(_ptr == nullptr);
151 clEnqueueSVMUnmap(q.get(), _ptr, 0, nullptr, nullptr);
152 _mapping = nullptr;
153}
154
Georgios Pinitas2cd5b312021-05-04 21:39:57 +0100155CLFineSVMMemoryRegion::CLFineSVMMemoryRegion(cl_mem_flags flags, size_t size, size_t alignment)
156 : ICLSVMMemoryRegion(flags, size, alignment)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100157{
158}
159
160void *CLFineSVMMemoryRegion::map(cl::CommandQueue &q, bool blocking)
161{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100162 if (blocking)
Georgios Pinitas99d40952018-04-23 16:26:46 +0100163 {
164 clFinish(q.get());
165 }
166 _mapping = _ptr;
167 return _mapping;
168}
169
170void CLFineSVMMemoryRegion::unmap(cl::CommandQueue &q)
171{
172 ARM_COMPUTE_UNUSED(q);
173 _mapping = nullptr;
174}
Pablo Tellodb8485a2019-09-24 11:03:47 +0100175} // namespace arm_compute