1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/delegates/gpu/cl/buffer.h"
17
18 #include <string>
19
20 #include "absl/status/status.h"
21 #include "tensorflow/lite/delegates/gpu/common/data_type.h"
22 #include "tensorflow/lite/delegates/gpu/common/status.h"
23
24 namespace tflite {
25 namespace gpu {
26 namespace cl {
27 namespace {
28
CreateBuffer(size_t size_in_bytes,bool gpu_read_only,const void * data,CLContext * context,Buffer * result)29 absl::Status CreateBuffer(size_t size_in_bytes, bool gpu_read_only,
30 const void* data, CLContext* context,
31 Buffer* result) {
32 cl_mem buffer;
33 RETURN_IF_ERROR(CreateCLBuffer(context->context(), size_in_bytes,
34 gpu_read_only, const_cast<void*>(data),
35 &buffer));
36 *result = Buffer(buffer, size_in_bytes);
37
38 return absl::OkStatus();
39 }
40
CreateSubBuffer(const Buffer & parent,size_t origin_in_bytes,size_t size_in_bytes,bool gpu_read_only,CLContext * context,Buffer * result)41 absl::Status CreateSubBuffer(const Buffer& parent, size_t origin_in_bytes,
42 size_t size_in_bytes, bool gpu_read_only,
43 CLContext* context, Buffer* result) {
44 cl_mem buffer;
45 if (parent.IsSubBuffer()) {
46 return absl::InvalidArgumentError(
47 "Cannot create a sub-buffer from a sub-buffer!");
48 }
49 RETURN_IF_ERROR(CreateCLSubBuffer(context->context(), parent.GetMemoryPtr(),
50 origin_in_bytes, size_in_bytes,
51 gpu_read_only, &buffer));
52 *result = Buffer(buffer, size_in_bytes, /*is_sub_buffer=*/true);
53
54 return absl::OkStatus();
55 }
56 } // namespace
57
Buffer(cl_mem buffer,size_t size_in_bytes,bool is_sub_buffer)58 Buffer::Buffer(cl_mem buffer, size_t size_in_bytes, bool is_sub_buffer)
59 : buffer_(buffer), size_(size_in_bytes), is_sub_buffer_(is_sub_buffer) {}
60
Buffer(Buffer && buffer)61 Buffer::Buffer(Buffer&& buffer)
62 : buffer_(buffer.buffer_),
63 size_(buffer.size_),
64 is_sub_buffer_(buffer.is_sub_buffer_) {
65 buffer.buffer_ = nullptr;
66 buffer.size_ = 0;
67 buffer.is_sub_buffer_ = false;
68 }
69
operator =(Buffer && buffer)70 Buffer& Buffer::operator=(Buffer&& buffer) {
71 if (this != &buffer) {
72 Release();
73 std::swap(size_, buffer.size_);
74 std::swap(buffer_, buffer.buffer_);
75 std::swap(is_sub_buffer_, buffer.is_sub_buffer_);
76 }
77 return *this;
78 }
79
Release()80 void Buffer::Release() {
81 if (buffer_) {
82 clReleaseMemObject(buffer_);
83 buffer_ = nullptr;
84 size_ = 0;
85 is_sub_buffer_ = false;
86 }
87 }
88
GetGPUResources(const GPUObjectDescriptor * obj_ptr,GPUResourcesWithValue * resources) const89 absl::Status Buffer::GetGPUResources(const GPUObjectDescriptor* obj_ptr,
90 GPUResourcesWithValue* resources) const {
91 const auto* buffer_desc = dynamic_cast<const BufferDescriptor*>(obj_ptr);
92 if (!buffer_desc) {
93 return absl::InvalidArgumentError("Expected BufferDescriptor on input.");
94 }
95
96 resources->buffers.push_back({"buffer", buffer_});
97 return absl::OkStatus();
98 }
99
CreateFromBufferDescriptor(const BufferDescriptor & desc,CLContext * context)100 absl::Status Buffer::CreateFromBufferDescriptor(const BufferDescriptor& desc,
101 CLContext* context) {
102 bool read_only = desc.memory_type == MemoryType::CONSTANT;
103 uint8_t* data_ptr = desc.data.empty()
104 ? nullptr
105 : const_cast<unsigned char*>(desc.data.data());
106 size_ = desc.size;
107 return CreateCLBuffer(context->context(), desc.size, read_only, data_ptr,
108 &buffer_);
109 }
110
CreateReadOnlyBuffer(size_t size_in_bytes,CLContext * context,Buffer * result)111 absl::Status CreateReadOnlyBuffer(size_t size_in_bytes, CLContext* context,
112 Buffer* result) {
113 return CreateBuffer(size_in_bytes, true, nullptr, context, result);
114 }
115
CreateReadOnlyBuffer(size_t size_in_bytes,const void * data,CLContext * context,Buffer * result)116 absl::Status CreateReadOnlyBuffer(size_t size_in_bytes, const void* data,
117 CLContext* context, Buffer* result) {
118 return CreateBuffer(size_in_bytes, true, data, context, result);
119 }
120
CreateReadWriteBuffer(size_t size_in_bytes,CLContext * context,Buffer * result)121 absl::Status CreateReadWriteBuffer(size_t size_in_bytes, CLContext* context,
122 Buffer* result) {
123 return CreateBuffer(size_in_bytes, false, nullptr, context, result);
124 }
125
CreateReadWriteSubBuffer(const Buffer & parent,size_t origin_in_bytes,size_t size_in_bytes,CLContext * context,Buffer * result)126 absl::Status CreateReadWriteSubBuffer(const Buffer& parent,
127 size_t origin_in_bytes,
128 size_t size_in_bytes, CLContext* context,
129 Buffer* result) {
130 return CreateSubBuffer(parent, origin_in_bytes, size_in_bytes,
131 /*gpu_read_only=*/false, context, result);
132 }
133
134 } // namespace cl
135 } // namespace gpu
136 } // namespace tflite
137